Merge "Avoid crashing in RunDumpsysProto when not zipping" into pi-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 0701450..21d9ace 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -116,7 +116,8 @@
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
{ "network", "Network", ATRACE_TAG_NETWORK, { } },
{ "adb", "ADB", ATRACE_TAG_ADB, { } },
- { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, {}},
+ { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } },
+ { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ k_pdxServiceCategory, "PDX services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 39fddc5..8e393c0 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -378,8 +378,7 @@
}
if (findAndBumpVersion(hal, version)) {
if (&table != &mImplementationsTable) {
- hal->interfaces[interfaceName].name = interfaceName;
- hal->interfaces[interfaceName].instances.insert(instanceName);
+ hal->insertLegacyInstance(interfaceName, instanceName);
}
hal->transportArch.arch |= arch;
done = true;
@@ -389,17 +388,16 @@
if (done) {
continue; // to next TableEntry
}
- decltype(vintf::ManifestHal::interfaces) interfaces;
- if (&table != &mImplementationsTable) {
- interfaces[interfaceName].name = interfaceName;
- interfaces[interfaceName].instances.insert(instanceName);
- }
- if (!manifest.add(vintf::ManifestHal{
+ vintf::ManifestHal manifestHal{
vintf::HalFormat::HIDL,
std::string{fqName.package()},
{version},
{transport, arch},
- std::move(interfaces)})) {
+ {}};
+ if (&table != &mImplementationsTable) {
+ manifestHal.insertLegacyInstance(interfaceName, instanceName);
+ }
+ if (!manifest.add(std::move(manifestHal))) {
err() << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
}
}
@@ -408,7 +406,7 @@
<< " This is a skeleton " << manifest.type() << " manifest. Notes: " << std::endl
<< INIT_VINTF_NOTES
<< "-->" << std::endl;
- out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_ONLY);
+ out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlag::HALS_NO_FQNAME);
}
std::string ListCommand::INIT_VINTF_NOTES{
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b7bf964..47f4e46 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -144,31 +144,31 @@
void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
if (connection == Connection::Connected) {
- auto display = getDisplayById(displayId);
- if (display) {
- if (display->isConnected()) {
- ALOGW("Attempt to hotplug connect display %" PRIu64
- " , which is already connected.", displayId);
- } else {
- display->setConnected(true);
- }
- } else {
- DisplayType displayType;
- auto intError = mComposer->getDisplayType(displayId,
- reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
- &displayType));
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
- "Aborting hotplug attempt.",
- displayId, to_string(error).c_str(), intError);
- return;
- }
-
- auto newDisplay = std::make_unique<Display>(
- *mComposer.get(), mCapabilities, displayId, displayType);
- mDisplays.emplace(displayId, std::move(newDisplay));
+ // If we get a hotplug connected event for a display we already have,
+ // destroy the display and recreate it. This will force us to requery
+ // the display params and recreate all layers on that display.
+ auto oldDisplay = getDisplayById(displayId);
+ if (oldDisplay != nullptr && oldDisplay->isConnected()) {
+ ALOGI("Hotplug connecting an already connected display."
+ " Clearing old display state.");
}
+ mDisplays.erase(displayId);
+
+ DisplayType displayType;
+ auto intError = mComposer->getDisplayType(displayId,
+ reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
+ &displayType));
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
+ "Aborting hotplug attempt.",
+ displayId, to_string(error).c_str(), intError);
+ return;
+ }
+
+ auto newDisplay = std::make_unique<Display>(
+ *mComposer.get(), mCapabilities, displayId, displayType);
+ mDisplays.emplace(displayId, std::move(newDisplay));
} else if (connection == Connection::Disconnected) {
// The display will later be destroyed by a call to
// destroyDisplay(). For now we just mark it disconnected.
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 7a43ea9..6a34981 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -305,15 +305,24 @@
if (needs.hasToneMapping()) {
fs << R"__SHADER__(
- float ToneMapChannel(const float color) {
+ float CalculateY(const vec3 color) {
+ // BT2020 standard uses the unadjusted KR = 0.2627,
+ // KB = 0.0593 luminance interpretation for RGB conversion.
+ return color.r * 0.262700 + color.g * 0.677998 +
+ color.b * 0.059302;
+ }
+ vec3 ToneMap(const vec3 color) {
const float maxLumi = 10000.0;
const float maxMasteringLumi = 1000.0;
const float maxContentLumi = 1000.0;
const float maxInLumi = min(maxMasteringLumi, maxContentLumi);
const float maxOutLumi = 500.0;
+ // Calculate Y value in XYZ color space.
+ float colorY = CalculateY(color);
+
// convert to nits first
- float nits = color * maxLumi;
+ float nits = colorY * maxLumi;
// clamp to max input luminance
nits = clamp(nits, 0.0, maxInLumi);
@@ -360,12 +369,8 @@
}
// convert back to [0.0, 1.0]
- return nits / maxOutLumi;
- }
-
- vec3 ToneMap(const vec3 color) {
- return vec3(ToneMapChannel(color.r), ToneMapChannel(color.g),
- ToneMapChannel(color.b));
+ float targetY = nits / maxOutLumi;
+ return color * (targetY / max(1e-6, colorY));
}
)__SHADER__";
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 11658e8..a6e0a9e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2120,16 +2120,16 @@
getBE().mHwc->onHotplug(event.display, displayType, event.connection);
if (event.connection == HWC2::Connection::Connected) {
- ALOGV("Creating built in display %d", displayType);
- ALOGW_IF(mBuiltinDisplays[displayType],
- "Overwriting display token for display type %d", displayType);
- mBuiltinDisplays[displayType] = new BBinder();
- // All non-virtual displays are currently considered secure.
- DisplayDeviceState info(displayType, true);
- info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ?
- "Built-in Screen" : "External Screen";
- mCurrentState.displays.add(mBuiltinDisplays[displayType], info);
- mInterceptor.saveDisplayCreation(info);
+ if (!mBuiltinDisplays[displayType].get()) {
+ ALOGV("Creating built in display %d", displayType);
+ mBuiltinDisplays[displayType] = new BBinder();
+ // All non-virtual displays are currently considered secure.
+ DisplayDeviceState info(displayType, true);
+ info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ?
+ "Built-in Screen" : "External Screen";
+ mCurrentState.displays.add(mBuiltinDisplays[displayType], info);
+ mInterceptor.saveDisplayCreation(info);
+ }
} else {
ALOGV("Removing built in display %d", displayType);
@@ -3980,7 +3980,7 @@
LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
- result.append(LayerProtoParser::layersToString(layerTree).c_str());
+ result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str());
/*
* Dump Display state
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index bf37e1e..c9b7fe5 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include <android-base/stringprintf.h>
#include <layerproto/LayerProtoParser.h>
#include <ui/DebugUtils.h>
@@ -24,7 +23,7 @@
namespace android {
namespace surfaceflinger {
-bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
+bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
uint32_t ls = lhs->layerStack;
uint32_t rs = rhs->layerStack;
if (ls != rs) return ls < rs;
@@ -38,20 +37,25 @@
return lhs->id < rhs->id;
}
-std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree(
+bool sortLayerUniquePtrs(const std::unique_ptr<LayerProtoParser::Layer>& lhs,
+ const std::unique_ptr<LayerProtoParser::Layer>& rhs) {
+ return sortLayers(lhs.get(), rhs.get());
+}
+
+std::vector<std::unique_ptr<LayerProtoParser::Layer>> LayerProtoParser::generateLayerTree(
const LayersProto& layersProto) {
- auto layerMap = generateMap(layersProto);
+ std::unordered_map<int32_t, LayerProtoParser::Layer*> layerMap = generateMap(layersProto);
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers;
- std::vector<const Layer*> layers;
- std::for_each(layerMap.begin(), layerMap.end(),
- [&](const std::pair<const int32_t, Layer*>& ref) {
- if (ref.second->parent == nullptr) {
- // only save top level layers
- layers.push_back(ref.second);
- }
- });
+ for (std::pair<int32_t, Layer*> kv : layerMap) {
+ if (kv.second->parent == nullptr) {
+ // Make unique_ptr for top level layers since they are not children. This ensures there
+ // will only be one unique_ptr made for each layer.
+ layers.push_back(std::unique_ptr<Layer>(kv.second));
+ }
+ }
- std::sort(layers.begin(), layers.end(), sortLayers);
+ std::sort(layers.begin(), layers.end(), sortLayerUniquePtrs);
return layers;
}
@@ -155,63 +159,61 @@
for (int i = 0; i < layerProto.children_size(); i++) {
if (layerMap.count(layerProto.children(i)) > 0) {
- auto childLayer = layerMap[layerProto.children(i)];
- currLayer->children.push_back(childLayer);
+ // Only make unique_ptrs for children since they are guaranteed to be unique, only one
+ // parent per child. This ensures there will only be one unique_ptr made for each layer.
+ currLayer->children.push_back(std::unique_ptr<Layer>(layerMap[layerProto.children(i)]));
}
}
for (int i = 0; i < layerProto.relatives_size(); i++) {
if (layerMap.count(layerProto.relatives(i)) > 0) {
- auto relativeLayer = layerMap[layerProto.relatives(i)];
- currLayer->relatives.push_back(relativeLayer);
+ currLayer->relatives.push_back(layerMap[layerProto.relatives(i)]);
}
}
if (layerProto.has_parent()) {
if (layerMap.count(layerProto.parent()) > 0) {
- auto parentLayer = layerMap[layerProto.parent()];
- currLayer->parent = parentLayer;
+ currLayer->parent = layerMap[layerProto.parent()];
}
}
if (layerProto.has_z_order_relative_of()) {
if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
- auto relativeLayer = layerMap[layerProto.z_order_relative_of()];
- currLayer->zOrderRelativeOf = relativeLayer;
+ currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()];
}
}
}
std::string LayerProtoParser::layersToString(
- const std::vector<const LayerProtoParser::Layer*> layers) {
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers) {
std::string result;
- for (const LayerProtoParser::Layer* layer : layers) {
+ for (std::unique_ptr<LayerProtoParser::Layer>& layer : layers) {
if (layer->zOrderRelativeOf != nullptr) {
continue;
}
- result.append(layerToString(layer).c_str());
+ result.append(layerToString(layer.get()).c_str());
}
return result;
}
-std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) {
+std::string LayerProtoParser::layerToString(LayerProtoParser::Layer* layer) {
std::string result;
- std::vector<const Layer*> traverse(layer->relatives);
- for (const LayerProtoParser::Layer* child : layer->children) {
+ std::vector<Layer*> traverse(layer->relatives);
+ for (std::unique_ptr<LayerProtoParser::Layer>& child : layer->children) {
if (child->zOrderRelativeOf != nullptr) {
continue;
}
- traverse.push_back(child);
+ traverse.push_back(child.get());
}
std::sort(traverse.begin(), traverse.end(), sortLayers);
size_t i = 0;
for (; i < traverse.size(); i++) {
- const auto& relative = traverse[i];
+ auto& relative = traverse[i];
if (relative->z >= 0) {
break;
}
@@ -220,7 +222,7 @@
result.append(layer->to_string().c_str());
result.append("\n");
for (; i < traverse.size(); i++) {
- const auto& relative = traverse[i];
+ auto& relative = traverse[i];
result.append(layerToString(relative).c_str());
}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 78c6cd1..b81a959 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -18,6 +18,7 @@
#include <math/vec4.h>
+#include <memory>
#include <unordered_map>
#include <vector>
@@ -68,8 +69,8 @@
public:
int32_t id;
std::string name;
- std::vector<const Layer*> children;
- std::vector<const Layer*> relatives;
+ std::vector<std::unique_ptr<Layer>> children;
+ std::vector<Layer*> relatives;
std::string type;
LayerProtoParser::Region transparentRegion;
LayerProtoParser::Region visibleRegion;
@@ -99,8 +100,8 @@
std::string to_string() const;
};
- static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
- static std::string layersToString(const std::vector<const LayerProtoParser::Layer*> layers);
+ static std::vector<std::unique_ptr<Layer>> generateLayerTree(const LayersProto& layersProto);
+ static std::string layersToString(std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers);
private:
static std::unordered_map<int32_t, Layer*> generateMap(const LayersProto& layersProto);
@@ -113,7 +114,7 @@
static void updateChildrenAndRelative(const LayerProto& layerProto,
std::unordered_map<int32_t, Layer*>& layerMap);
- static std::string layerToString(const LayerProtoParser::Layer* layer);
+ static std::string layerToString(LayerProtoParser::Layer* layer);
};
} // namespace surfaceflinger
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 7d3da32..7523399 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -33,6 +33,7 @@
"libEGL",
"libGLESv2",
"libgui",
+ "liblayers_proto",
"liblog",
"libprotobuf-cpp-full",
"libui",
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 33dd2f5..4577153 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -22,7 +22,7 @@
#include <thread>
#include <functional>
-
+#include <layerproto/LayerProtoParser.h>
namespace android {
@@ -47,4 +47,66 @@
}
}
+surfaceflinger::LayersProto generateLayerProto() {
+ surfaceflinger::LayersProto layersProto;
+ std::array<surfaceflinger::LayerProto*, 10> layers = {};
+ for (size_t i = 0; i < layers.size(); ++i) {
+ layers[i] = layersProto.add_layers();
+ layers[i]->set_id(i);
+ }
+
+ layers[0]->add_children(1);
+ layers[1]->set_parent(0);
+ layers[0]->add_children(2);
+ layers[2]->set_parent(0);
+ layers[0]->add_children(3);
+ layers[3]->set_parent(0);
+ layers[2]->add_children(4);
+ layers[4]->set_parent(2);
+ layers[3]->add_children(5);
+ layers[5]->set_parent(3);
+ layers[5]->add_children(6);
+ layers[6]->set_parent(5);
+ layers[5]->add_children(7);
+ layers[7]->set_parent(5);
+ layers[6]->add_children(8);
+ layers[8]->set_parent(6);
+
+ layers[4]->set_z_order_relative_of(3);
+ layers[3]->add_relatives(4);
+ layers[8]->set_z_order_relative_of(9);
+ layers[9]->add_relatives(8);
+ layers[3]->set_z_order_relative_of(1);
+ layers[1]->add_relatives(3);
+
+/* ----------------------------
+ * - 0 - - 9 -
+ * / | \
+ * 1 2 3(1)
+ * | |
+ * 4(3) 5
+ * / \
+ * 6 7
+ * |
+ * 8(9)
+ * -------------------------- */
+
+ return layersProto;
+}
+
+TEST(LayerProtoStress, mem_info) {
+ std::string cmd = "dumpsys meminfo ";
+ cmd += std::to_string(getpid());
+ system(cmd.c_str());
+ for (int i = 0; i < 100000; i++) {
+ surfaceflinger::LayersProto layersProto = generateLayerProto();
+ auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto);
+ // Allow some layerTrees to just fall out of scope (instead of std::move)
+ if (i % 2) {
+ surfaceflinger::LayerProtoParser::layersToString(std::move(layerTree));
+ }
+ }
+ system(cmd.c_str());
+}
+
}