diff options
| author | 2018-03-24 01:00:38 +0000 | |
|---|---|---|
| committer | 2018-03-24 01:00:38 +0000 | |
| commit | 2e971a918ce1f6ea51fe0c504766c77fd18a8676 (patch) | |
| tree | a83152670fc938da7443243c5f8877a71c5f7065 | |
| parent | c1bb0157eeeb0bc281e97fcf030a8371f830e1b8 (diff) | |
| parent | 7794ec15e59fd6dd389ba05379ff81287c6ab52f (diff) | |
Merge "Use unique_ptr for proto parser to handle destruction." into pi-dev
5 files changed, 105 insertions, 39 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7e02922405..a6e0a9ec98 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3980,7 +3980,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, 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 bf37e1e156..c9b7fe55b8 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 @@ using android::base::StringPrintf; 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 @@ bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Laye 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::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); - } - }); - - std::sort(layers.begin(), layers.end(), sortLayers); + std::unordered_map<int32_t, LayerProtoParser::Layer*> layerMap = generateMap(layersProto); + std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers; + + 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(), sortLayerUniquePtrs); return layers; } @@ -155,63 +159,61 @@ void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, 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 @@ std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer 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 78c6cd1345..b81a9595d2 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: 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 @@ public: 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 @@ private: 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 7d3da329ce..7523399dbf 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -33,6 +33,7 @@ cc_test { "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 33dd2f55d3..4577153df2 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 @@ TEST(SurfaceFlingerStress, create_and_destroy) { } } +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()); +} + } |