Merge "Add captureLayers function to capture a layer and its children."
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 239a2d5..c36ab08 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -62,6 +62,8 @@
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
" -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
+ " --proto: filter services that support dumping data in proto format. Dumps"
+ " will be in proto format.\n"
" --priority LEVEL: filter services based on specified priority\n"
" LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
" --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
@@ -77,17 +79,17 @@
return false;
}
-static bool ConvertPriorityTypeToBitmask(String16& type, int& bitmask) {
- if (type == PRIORITY_ARG_CRITICAL) {
- bitmask = IServiceManager::DUMP_PRIORITY_CRITICAL;
+static bool ConvertPriorityTypeToBitmask(const String16& type, int& bitmask) {
+ if (type == PriorityDumper::PRIORITY_ARG_CRITICAL) {
+ bitmask = IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL;
return true;
}
- if (type == PRIORITY_ARG_HIGH) {
- bitmask = IServiceManager::DUMP_PRIORITY_HIGH;
+ if (type == PriorityDumper::PRIORITY_ARG_HIGH) {
+ bitmask = IServiceManager::DUMP_FLAG_PRIORITY_HIGH;
return true;
}
- if (type == PRIORITY_ARG_NORMAL) {
- bitmask = IServiceManager::DUMP_PRIORITY_NORMAL;
+ if (type == PriorityDumper::PRIORITY_ARG_NORMAL) {
+ bitmask = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL;
return true;
}
return false;
@@ -98,11 +100,14 @@
Vector<String16> args;
String16 priorityType;
Vector<String16> skippedServices;
+ Vector<String16> protoServices;
bool showListOnly = false;
bool skipServices = false;
+ bool filterByProto = false;
int timeoutArg = 10;
- int dumpPriority = IServiceManager::DUMP_PRIORITY_ALL;
+ int dumpPriorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
static struct option longOptions[] = {{"priority", required_argument, 0, 0},
+ {"proto", no_argument, 0, 0},
{"skip", no_argument, 0, 0},
{"help", no_argument, 0, 0},
{0, 0, 0, 0}};
@@ -124,12 +129,14 @@
case 0:
if (!strcmp(longOptions[optionIndex].name, "skip")) {
skipServices = true;
+ } else if (!strcmp(longOptions[optionIndex].name, "proto")) {
+ filterByProto = true;
} else if (!strcmp(longOptions[optionIndex].name, "help")) {
usage();
return 0;
} else if (!strcmp(longOptions[optionIndex].name, "priority")) {
priorityType = String16(String8(optarg));
- if (!ConvertPriorityTypeToBitmask(priorityType, dumpPriority)) {
+ if (!ConvertPriorityTypeToBitmask(priorityType, dumpPriorityFlags)) {
fprintf(stderr, "\n");
usage();
return -1;
@@ -179,10 +186,19 @@
if (services.empty() || showListOnly) {
// gets all services
- services = sm_->listServices(dumpPriority);
+ services = sm_->listServices(dumpPriorityFlags);
services.sort(sort_func);
- if (dumpPriority != IServiceManager::DUMP_PRIORITY_ALL) {
- args.insertAt(String16(PRIORITY_ARG), 0);
+ if (filterByProto) {
+ protoServices = sm_->listServices(IServiceManager::DUMP_FLAG_PROTO);
+ protoServices.sort(sort_func);
+ Vector<String16> intersection;
+ std::set_intersection(services.begin(), services.end(), protoServices.begin(),
+ protoServices.end(), std::back_inserter(intersection));
+ services = std::move(intersection);
+ args.insertAt(String16(PriorityDumper::PROTO_ARG), 0);
+ }
+ if (dumpPriorityFlags != IServiceManager::DUMP_FLAG_PRIORITY_ALL) {
+ args.insertAt(String16(PriorityDumper::PRIORITY_ARG), 0);
args.insertAt(priorityType, 1);
} else {
args.add(String16("-a"));
@@ -230,7 +246,7 @@
if (N > 1) {
aout << "------------------------------------------------------------"
"-------------------" << endl;
- if (dumpPriority == IServiceManager::DUMP_PRIORITY_ALL) {
+ if (dumpPriorityFlags == IServiceManager::DUMP_FLAG_PRIORITY_ALL) {
aout << "DUMP OF SERVICE " << service_name << ":" << endl;
} else {
aout << "DUMP OF SERVICE " << priorityType << " " << service_name << ":" << endl;
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index 39fcb80..e182b9d 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -15,6 +15,7 @@
static_libs: [
"libdumpsys",
"libgmock",
+ "libserviceutils",
],
clang: true,
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 9fe4572..18a4da9 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <android-base/file.h>
+#include <serviceutils/PriorityDumper.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -131,16 +132,16 @@
for (auto& service : services) {
services16.add(String16(service.c_str()));
}
- EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_PRIORITY_ALL))
+ EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL))
.WillRepeatedly(Return(services16));
}
- void ExpectListServicesWithPriority(std::vector<std::string> services, int dumpPriority) {
+ void ExpectListServicesWithPriority(std::vector<std::string> services, int dumpFlags) {
Vector<String16> services16;
for (auto& service : services) {
services16.add(String16(service.c_str()));
}
- EXPECT_CALL(sm_, listServices(dumpPriority)).WillRepeatedly(Return(services16));
+ EXPECT_CALL(sm_, listServices(dumpFlags)).WillRepeatedly(Return(services16));
}
sp<BinderMock> ExpectCheckService(const char* name, bool running = true) {
@@ -210,6 +211,13 @@
EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
}
+ void AssertDumpedWithPriority(const std::string& service, const std::string& dump,
+ const char16_t* priorityType) {
+ std::string priority = String8(priorityType).c_str();
+ EXPECT_THAT(stdout_,
+ HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump));
+ }
+
void AssertNotDumped(const std::string& dump) {
EXPECT_THAT(stdout_, Not(HasSubstr(dump)));
}
@@ -250,7 +258,7 @@
// Tests 'dumpsys -l --priority HIGH'
TEST_F(DumpsysTest, ListAllServicesWithPriority) {
- ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_PRIORITY_HIGH);
+ ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
ExpectCheckService("Locksmith");
ExpectCheckService("Valet");
@@ -261,13 +269,26 @@
// Tests 'dumpsys -l --priority HIGH' with and empty list
TEST_F(DumpsysTest, ListEmptyServicesWithPriority) {
- ExpectListServicesWithPriority({}, IServiceManager::DUMP_PRIORITY_HIGH);
+ ExpectListServicesWithPriority({}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
CallMain({"-l", "--priority", "HIGH"});
AssertRunningServices({});
}
+// Tests 'dumpsys -l --proto'
+TEST_F(DumpsysTest, ListAllServicesWithProto) {
+ ExpectListServicesWithPriority({"Locksmith", "Valet", "Car"},
+ IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ ExpectListServicesWithPriority({"Valet", "Car"}, IServiceManager::DUMP_FLAG_PROTO);
+ ExpectCheckService("Car");
+ ExpectCheckService("Valet");
+
+ CallMain({"-l", "--proto"});
+
+ AssertRunningServices({"Car", "Valet"});
+}
+
// Tests 'dumpsys service_name' on a service is running
TEST_F(DumpsysTest, DumpRunningService) {
ExpectDump("Valet", "Here's your car");
@@ -336,7 +357,7 @@
// Tests 'dumpsys --skip skipped3 skipped5 --priority CRITICAL', which should skip these services
TEST_F(DumpsysTest, DumpWithSkipAndPriority) {
ExpectListServicesWithPriority({"running1", "stopped2", "skipped3", "running4", "skipped5"},
- IServiceManager::DUMP_PRIORITY_CRITICAL);
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
ExpectDump("running1", "dump1");
ExpectCheckService("stopped2", false);
ExpectDump("skipped3", "dump3");
@@ -346,8 +367,8 @@
CallMain({"--priority", "CRITICAL", "--skip", "skipped3", "skipped5"});
AssertRunningServices({"running1", "running4", "skipped3 (skipped)", "skipped5 (skipped)"});
- AssertDumped("running1", "dump1");
- AssertDumped("running4", "dump4");
+ AssertDumpedWithPriority("running1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL);
+ AssertDumpedWithPriority("running4", "dump4", PriorityDumper::PRIORITY_ARG_CRITICAL);
AssertStopped("stopped2");
AssertNotDumped("dump3");
AssertNotDumped("dump5");
@@ -356,41 +377,74 @@
// Tests 'dumpsys --priority CRITICAL'
TEST_F(DumpsysTest, DumpWithPriorityCritical) {
ExpectListServicesWithPriority({"runningcritical1", "runningcritical2"},
- IServiceManager::DUMP_PRIORITY_CRITICAL);
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
ExpectDump("runningcritical1", "dump1");
ExpectDump("runningcritical2", "dump2");
CallMain({"--priority", "CRITICAL"});
AssertRunningServices({"runningcritical1", "runningcritical2"});
- AssertDumped("runningcritical1", "dump1");
- AssertDumped("runningcritical2", "dump2");
+ AssertDumpedWithPriority("runningcritical1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL);
+ AssertDumpedWithPriority("runningcritical2", "dump2", PriorityDumper::PRIORITY_ARG_CRITICAL);
}
// Tests 'dumpsys --priority HIGH'
TEST_F(DumpsysTest, DumpWithPriorityHigh) {
ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"},
- IServiceManager::DUMP_PRIORITY_HIGH);
+ IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
ExpectDump("runninghigh1", "dump1");
ExpectDump("runninghigh2", "dump2");
CallMain({"--priority", "HIGH"});
AssertRunningServices({"runninghigh1", "runninghigh2"});
- AssertDumped("runninghigh1", "dump1");
- AssertDumped("runninghigh2", "dump2");
+ AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH);
+ AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
}
// Tests 'dumpsys --priority NORMAL'
TEST_F(DumpsysTest, DumpWithPriorityNormal) {
ExpectListServicesWithPriority({"runningnormal1", "runningnormal2"},
- IServiceManager::DUMP_PRIORITY_NORMAL);
+ IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
ExpectDump("runningnormal1", "dump1");
ExpectDump("runningnormal2", "dump2");
CallMain({"--priority", "NORMAL"});
AssertRunningServices({"runningnormal1", "runningnormal2"});
- AssertDumped("runningnormal1", "dump1");
- AssertDumped("runningnormal2", "dump2");
+ AssertDumpedWithPriority("runningnormal1", "dump1", PriorityDumper::PRIORITY_ARG_NORMAL);
+ AssertDumpedWithPriority("runningnormal2", "dump2", PriorityDumper::PRIORITY_ARG_NORMAL);
+}
+
+// Tests 'dumpsys --proto'
+TEST_F(DumpsysTest, DumpWithProto) {
+ ExpectListServicesWithPriority({"run8", "run1", "run2", "run5"},
+ IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ ExpectListServicesWithPriority({"run3", "run2", "run4", "run8"},
+ IServiceManager::DUMP_FLAG_PROTO);
+ ExpectDump("run2", "dump1");
+ ExpectDump("run8", "dump2");
+
+ CallMain({"--proto"});
+
+ AssertRunningServices({"run2", "run8"});
+ AssertDumped("run2", "dump1");
+ AssertDumped("run8", "dump2");
+}
+
+// Tests 'dumpsys --priority HIGH --proto'
+TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) {
+ ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"},
+ IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+ ExpectListServicesWithPriority({"runninghigh1", "runninghigh2", "runninghigh3"},
+ IServiceManager::DUMP_FLAG_PROTO);
+
+ ExpectDump("runninghigh1", "dump1");
+ ExpectDump("runninghigh2", "dump2");
+
+ CallMain({"--priority", "HIGH", "--proto"});
+
+ AssertRunningServices({"runninghigh1", "runninghigh2"});
+ AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH);
+ AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 4bb8ebe..cbd67be 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1407,7 +1407,7 @@
argv[i++] = downgrade_flag;
}
if (class_loader_context != nullptr) {
- argv[i++] = class_loader_context;
+ argv[i++] = class_loader_context_arg.c_str();
}
argv[i] = NULL;
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index 4e69067..4ce82a1 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -35,15 +35,16 @@
{
public:
static status_t publish(bool allowIsolated = false,
- int dumpPriority = IServiceManager::DUMP_PRIORITY_NORMAL) {
+ int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
- dumpPriority);
+ dumpFlags);
}
- static void publishAndJoinThreadPool(bool allowIsolated = false,
- int dumpPriority = IServiceManager::DUMP_PRIORITY_NORMAL) {
- publish(allowIsolated, dumpPriority);
+ static void publishAndJoinThreadPool(
+ bool allowIsolated = false,
+ int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) {
+ publish(allowIsolated, dumpFlags);
joinThreadPool();
}
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 78b03bd..19e841a 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -34,11 +34,12 @@
/*
* Must match values in IServiceManager.java
*/
- static const int DUMP_PRIORITY_CRITICAL = 1 << 0;
- static const int DUMP_PRIORITY_HIGH = 1 << 1;
- static const int DUMP_PRIORITY_NORMAL = 1 << 2;
- static const int DUMP_PRIORITY_ALL =
- DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL;
+ static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
+ static const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
+ static const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
+ static const int DUMP_FLAG_PRIORITY_ALL =
+ DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL;
+ static const int DUMP_FLAG_PROTO = 1 << 3;
/**
* Retrieve an existing service, blocking for a few seconds
@@ -56,12 +57,12 @@
*/
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated = false,
- int dumpsysPriority = DUMP_PRIORITY_NORMAL) = 0;
+ int dumpsysFlags = DUMP_FLAG_PRIORITY_NORMAL) = 0;
/**
* Return list of all existing services.
*/
- virtual Vector<String16> listServices(int dumpsysPriority = DUMP_PRIORITY_ALL) = 0;
+ virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fe9409b..875bef1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3483,12 +3483,18 @@
// ---------------------------------------------------------------------------
-status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args) {
+status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto) {
String8 result;
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
+
+ if (asProto) {
+ // Return early as SurfaceFlinger does not support dumping sections in proto format
+ return OK;
+ }
+
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(sDump, pid, uid)) {
result.appendFormat("Permission Denial: "
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9975de9..25ccb89 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -604,11 +604,14 @@
* Debugging & dumpsys
*/
public:
- status_t dumpCritical(int fd, const Vector<String16>& /*args*/) {
- return doDump(fd, Vector<String16>());
+ status_t dumpCritical(int fd, const Vector<String16>& /*args*/, bool asProto) {
+ return doDump(fd, Vector<String16>(), asProto);
}
- status_t dumpAll(int fd, const Vector<String16>& args) { return doDump(fd, args); }
+ status_t dumpAll(int fd, const Vector<String16>& args, bool asProto) {
+ return doDump(fd, args, asProto);
+ }
+
private:
void listLayersLocked(const Vector<String16>& args, size_t& index, String8& result) const;
void dumpStatsLocked(const Vector<String16>& args, size_t& index, String8& result) const;
@@ -634,7 +637,7 @@
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
}
- status_t doDump(int fd, const Vector<String16>& args);
+ status_t doDump(int fd, const Vector<String16>& args, bool asProto);
#ifdef USE_HWC2
/* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 8c530e0..952023e 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -3009,13 +3009,18 @@
// ---------------------------------------------------------------------------
-status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args)
-{
+status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto) {
String8 result;
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
+
+ if (asProto) {
+ // Return early as SurfaceFlinger does not support dumping sections in proto format
+ return OK;
+ }
+
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(sDump, pid, uid)) {
result.appendFormat("Permission Denial: "
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 6554167..e6f2ce7 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -14,10 +14,16 @@
* limitations under the License.
*/
+#include <android-base/stringprintf.h>
#include <layerproto/LayerProtoParser.h>
+#include <ui/DebugUtils.h>
+
+using android::base::StringAppendF;
+using android::base::StringPrintf;
namespace android {
namespace surfaceflinger {
+
bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
uint32_t ls = lhs->layerStack;
uint32_t rs = rhs->layerStack;
@@ -219,5 +225,62 @@
return result;
}
+std::string LayerProtoParser::ActiveBuffer::to_string() const {
+ return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride,
+ decodePixelFormat(format).c_str());
+}
+
+std::string LayerProtoParser::Transform::to_string() const {
+ return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(dsdx),
+ static_cast<double>(dtdx), static_cast<double>(dsdy),
+ static_cast<double>(dtdy));
+}
+
+std::string LayerProtoParser::Rect::to_string() const {
+ return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom);
+}
+
+std::string LayerProtoParser::Region::to_string(const char* what) const {
+ std::string result =
+ StringPrintf(" Region %s (this=%lx count=%d)\n", what, static_cast<unsigned long>(id),
+ static_cast<int>(rects.size()));
+
+ for (auto& rect : rects) {
+ StringAppendF(&result, " %s\n", rect.to_string().c_str());
+ }
+
+ return result;
+}
+
+std::string LayerProtoParser::Layer::to_string() const {
+ std::string result;
+ StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str());
+ result.append(transparentRegion.to_string("TransparentRegion").c_str());
+ result.append(visibleRegion.to_string("VisibleRegion").c_str());
+ result.append(damageRegion.to_string("SurfaceDamageRegion").c_str());
+
+ StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ", layerStack,
+ z, static_cast<double>(position.x), static_cast<double>(position.y), size.x,
+ size.y);
+
+ StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(),
+ finalCrop.to_string().c_str());
+ StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
+ StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
+ StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
+ StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+ static_cast<double>(color.r), static_cast<double>(color.g),
+ static_cast<double>(color.b), static_cast<double>(color.a), flags);
+ StringAppendF(&result, "tr=%s", transform.to_string().c_str());
+ result.append("\n");
+ StringAppendF(&result, " parent=%s\n", parent == nullptr ? "none" : parent->name.c_str());
+ StringAppendF(&result, " zOrderRelativeOf=%s\n",
+ zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
+ StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str());
+ StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending);
+
+ return result;
+}
+
} // namespace surfaceflinger
} // namespace android
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 7b94cef..78c6cd1 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -18,14 +18,9 @@
#include <math/vec4.h>
-#include <android-base/stringprintf.h>
-#include <ui/DebugUtils.h>
#include <unordered_map>
#include <vector>
-using android::base::StringAppendF;
-using android::base::StringPrintf;
-
namespace android {
namespace surfaceflinger {
@@ -38,10 +33,7 @@
uint32_t stride;
int32_t format;
- std::string to_string() const {
- return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride,
- decodePixelFormat(format).c_str());
- }
+ std::string to_string() const;
};
class Transform {
@@ -51,11 +43,7 @@
float dsdy;
float dtdy;
- std::string to_string() const {
- return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(dsdx),
- static_cast<double>(dtdx), static_cast<double>(dsdy),
- static_cast<double>(dtdy));
- }
+ std::string to_string() const;
};
class Rect {
@@ -65,9 +53,7 @@
int32_t right;
int32_t bottom;
- std::string to_string() const {
- return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom);
- }
+ std::string to_string() const;
};
class Region {
@@ -75,17 +61,7 @@
uint64_t id;
std::vector<Rect> rects;
- std::string to_string(const char* what) const {
- std::string result =
- StringPrintf(" Region %s (this=%lx count=%d)\n", what,
- static_cast<unsigned long>(id), static_cast<int>(rects.size()));
-
- for (auto& rect : rects) {
- StringAppendF(&result, " %s\n", rect.to_string().c_str());
- }
-
- return result;
- }
+ std::string to_string(const char* what) const;
};
class Layer {
@@ -120,37 +96,7 @@
int32_t queuedFrames;
bool refreshPending;
- std::string to_string() const {
- std::string result;
- StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str());
- result.append(transparentRegion.to_string("TransparentRegion").c_str());
- result.append(visibleRegion.to_string("VisibleRegion").c_str());
- result.append(damageRegion.to_string("SurfaceDamageRegion").c_str());
-
- StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ",
- layerStack, z, static_cast<double>(position.x),
- static_cast<double>(position.y), size.x, size.y);
-
- StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(),
- finalCrop.to_string().c_str());
- StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
- StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
- StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
- StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
- static_cast<double>(color.r), static_cast<double>(color.g),
- static_cast<double>(color.b), static_cast<double>(color.a), flags);
- StringAppendF(&result, "tr=%s", transform.to_string().c_str());
- result.append("\n");
- StringAppendF(&result, " parent=%s\n",
- parent == nullptr ? "none" : parent->name.c_str());
- StringAppendF(&result, " zOrderRelativeOf=%s\n",
- zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
- StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str());
- StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames,
- refreshPending);
-
- return result;
- }
+ std::string to_string() const;
};
static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 6a24891..2a924ae 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -106,7 +106,7 @@
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
- IServiceManager::DUMP_PRIORITY_CRITICAL);
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
// publish GpuService
sp<GpuService> gpuservice = new GpuService();
diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp
index 9851188..967dee5 100644
--- a/services/utils/PriorityDumper.cpp
+++ b/services/utils/PriorityDumper.cpp
@@ -18,41 +18,68 @@
namespace android {
-static void getStrippedArgs(Vector<String16>& dest, const Vector<String16>& source,
- std::size_t numArgsToStrip) {
- for (auto it = source.begin() + numArgsToStrip; it != source.end(); it++) {
- dest.add(*it);
+const char16_t PriorityDumper::PROTO_ARG[] = u"--proto";
+const char16_t PriorityDumper::PRIORITY_ARG[] = u"--dump-priority";
+const char16_t PriorityDumper::PRIORITY_ARG_CRITICAL[] = u"CRITICAL";
+const char16_t PriorityDumper::PRIORITY_ARG_HIGH[] = u"HIGH";
+const char16_t PriorityDumper::PRIORITY_ARG_NORMAL[] = u"NORMAL";
+
+enum class PriorityType { INVALID, CRITICAL, HIGH, NORMAL };
+
+static PriorityType getPriorityType(const String16& arg) {
+ if (arg == PriorityDumper::PRIORITY_ARG_CRITICAL) {
+ return PriorityType::CRITICAL;
+ } else if (arg == PriorityDumper::PRIORITY_ARG_HIGH) {
+ return PriorityType::HIGH;
+ } else if (arg == PriorityDumper::PRIORITY_ARG_NORMAL) {
+ return PriorityType::NORMAL;
}
+ return PriorityType::INVALID;
}
-status_t PriorityDumper::dumpAll(int fd, const Vector<String16>& args) {
+status_t PriorityDumper::dumpAll(int fd, const Vector<String16>& args, bool asProto) {
status_t status;
- status = dumpCritical(fd, args);
+ status = dumpCritical(fd, args, asProto);
if (status != OK) return status;
- status = dumpHigh(fd, args);
+ status = dumpHigh(fd, args, asProto);
if (status != OK) return status;
- status = dumpNormal(fd, args);
+ status = dumpNormal(fd, args, asProto);
if (status != OK) return status;
return status;
}
status_t PriorityDumper::priorityDump(int fd, const Vector<String16>& args) {
status_t status;
- if (args.size() >= 2 && args[0] == PRIORITY_ARG) {
- String16 priority = args[1];
- Vector<String16> strippedArgs;
- getStrippedArgs(strippedArgs, args, 2);
- if (priority == PRIORITY_ARG_CRITICAL) {
- status = dumpCritical(fd, strippedArgs);
- } else if (priority == PRIORITY_ARG_HIGH) {
- status = dumpHigh(fd, strippedArgs);
- } else if (priority == PRIORITY_ARG_NORMAL) {
- status = dumpNormal(fd, strippedArgs);
+ bool asProto = false;
+ PriorityType priority = PriorityType::INVALID;
+
+ Vector<String16> strippedArgs;
+ for (uint32_t argIndex = 0; argIndex < args.size(); argIndex++) {
+ if (args[argIndex] == PROTO_ARG) {
+ asProto = true;
+ } else if (args[argIndex] == PRIORITY_ARG) {
+ if (argIndex + 1 < args.size()) {
+ argIndex++;
+ priority = getPriorityType(args[argIndex]);
+ }
} else {
- status = dumpAll(fd, args);
+ strippedArgs.add(args[argIndex]);
}
- } else {
- status = dumpAll(fd, args);
+ }
+
+ switch (priority) {
+ case PriorityType::CRITICAL:
+ status = dumpCritical(fd, strippedArgs, asProto);
+ break;
+ case PriorityType::HIGH:
+ status = dumpHigh(fd, strippedArgs, asProto);
+ break;
+ case PriorityType::NORMAL:
+ status = dumpNormal(fd, strippedArgs, asProto);
+ break;
+ default:
+ status = dumpAll(fd, strippedArgs, asProto);
+ break;
}
return status;
}
diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h
index 0319242..d01a102 100644
--- a/services/utils/include/serviceutils/PriorityDumper.h
+++ b/services/utils/include/serviceutils/PriorityDumper.h
@@ -23,34 +23,43 @@
namespace android {
-constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority";
-constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL";
-constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH";
-constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL";
-
-// Helper class to split dumps into various priority buckets.
+// Helper class to parse common arguments responsible for splitting dumps into
+// various priority buckets and changing the output format of the dump.
class PriorityDumper {
public:
- // Parses the argument list checking if the first argument is --dump_priority and
- // the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the
- // arguments are found, they are stripped and the appropriate PriorityDumper
- // method is called.
- // If --dump_priority argument is not passed, all supported sections are dumped.
+ static const char16_t PRIORITY_ARG[];
+ static const char16_t PRIORITY_ARG_CRITICAL[];
+ static const char16_t PRIORITY_ARG_HIGH[];
+ static const char16_t PRIORITY_ARG_NORMAL[];
+ static const char16_t PROTO_ARG[];
+
+ // Parses the argument list searching for --dump_priority with a priority type
+ // (HIGH, CRITICAL or NORMAL) and --proto. Matching arguments are stripped.
+ // If a valid priority type is found, the associated PriorityDumper
+ // method is called otherwise all supported sections are dumped.
+ // If --proto is found, the dumpAsProto flag is set to dump sections in proto
+ // format.
status_t priorityDump(int fd, const Vector<String16>& args);
// Dumps CRITICAL priority sections.
- virtual status_t dumpCritical(int /*fd*/, const Vector<String16>& /*args*/) { return OK; }
+ virtual status_t dumpCritical(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ return OK;
+ }
// Dumps HIGH priority sections.
- virtual status_t dumpHigh(int /*fd*/, const Vector<String16>& /*args*/) { return OK; }
+ virtual status_t dumpHigh(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ return OK;
+ }
// Dumps normal priority sections.
- virtual status_t dumpNormal(int /*fd*/, const Vector<String16>& /*args*/) { return OK; }
+ virtual status_t dumpNormal(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ return OK;
+ }
// Dumps all sections.
// This method is called when priorityDump is called without priority
// arguments. By default, it calls all three dump methods.
- virtual status_t dumpAll(int fd, const Vector<String16>& args);
+ virtual status_t dumpAll(int fd, const Vector<String16>& args, bool asProto);
virtual ~PriorityDumper() = default;
};
diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp
index 79e7340..90cc6de 100644
--- a/services/utils/tests/PriorityDumper_test.cpp
+++ b/services/utils/tests/PriorityDumper_test.cpp
@@ -32,17 +32,17 @@
class PriorityDumperMock : public PriorityDumper {
public:
- MOCK_METHOD2(dumpCritical, status_t(int, const Vector<String16>&));
- MOCK_METHOD2(dumpHigh, status_t(int, const Vector<String16>&));
- MOCK_METHOD2(dumpNormal, status_t(int, const Vector<String16>&));
- MOCK_METHOD2(dumpAll, status_t(int, const Vector<String16>&));
+ MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpAll, status_t(int, const Vector<String16>&, bool));
};
class DumpAllMock : public PriorityDumper {
public:
- MOCK_METHOD2(dumpCritical, status_t(int, const Vector<String16>&));
- MOCK_METHOD2(dumpHigh, status_t(int, const Vector<String16>&));
- MOCK_METHOD2(dumpNormal, status_t(int, const Vector<String16>&));
+ MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
};
class PriorityDumperTest : public Test {
@@ -61,14 +61,14 @@
TEST_F(PriorityDumperTest, noArgsPassed) {
Vector<String16> args;
- EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args)));
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
TEST_F(PriorityDumperTest, noPriorityArgsPassed) {
Vector<String16> args;
addAll(args, {"bunch", "of", "args"});
- EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args)));
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
@@ -76,7 +76,7 @@
Vector<String16> args;
addAll(args, {"--dump-priority", "CRITICAL"});
Vector<String16> strippedArgs;
- EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs)));
+ EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
@@ -86,7 +86,17 @@
Vector<String16> strippedArgs;
addAll(strippedArgs, {"args", "left", "behind"});
- EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs)));
+ EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpCriticalInMiddle) {
+ Vector<String16> args;
+ addAll(args, {"args", "left", "--dump-priority", "CRITICAL", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
@@ -96,7 +106,17 @@
Vector<String16> strippedArgs;
addAll(strippedArgs, {"args", "left", "behind"});
- EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs)));
+ EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpHighInEnd) {
+ Vector<String16> args;
+ addAll(args, {"args", "left", "behind", "--dump-priority", "HIGH"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
@@ -106,7 +126,7 @@
Vector<String16> strippedArgs;
addAll(strippedArgs, {"args", "left", "behind"});
- EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs)));
+ EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
@@ -114,9 +134,9 @@
Vector<String16> args;
addAll(args, {"args", "left", "behind"});
- EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args)));
- EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args)));
- EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args)));
+ EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args), /*asProto=*/false));
+ EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args), /*asProto=*/false));
+ EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args), /*asProto=*/false));
dumpAlldumper_.priorityDump(fd, args);
}
@@ -124,7 +144,8 @@
TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) {
Vector<String16> args;
addAll(args, {"--dump-priority"});
- EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args)));
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
dumper_.priorityDump(fd, args);
}
@@ -132,7 +153,67 @@
TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) {
Vector<String16> args;
addAll(args, {"--dump-priority", "REALLY_HIGH"});
- EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args)));
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArg) {
+ Vector<String16> args;
+ addAll(args, {"--proto"});
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithPriorityArgs) {
+ Vector<String16> args;
+ addAll(args, {"--proto", "args", "--dump-priority", "NORMAL", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithPriorityArgsInReverseOrder) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "NORMAL", "--proto", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgInMiddle) {
+ Vector<String16> args;
+ addAll(args, {"--unknown", "args", "--proto", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgAtEnd) {
+ Vector<String16> args;
+ addAll(args, {"--unknown", "args", "args", "left", "behind", "--proto"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithInvalidPriorityType) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "NOT_SO_HIGH", "--proto", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
dumper_.priorityDump(fd, args);
}
\ No newline at end of file