Expose binder stability for debugging in dumpsys
See if a service is coupled with the system/core build variant or build
variant (or if the service has 'vintf' stability - meaning it is used as
a HAL). This will also print additional information about the version of
the binder wire protocol that is being used by this object (currently
everything uses the same version - this may be the case for a while).
Fixes: 184062810
Test: dumpsys_test
Test: manually running 'dumpsys --stability' and 'dumpsys --help'
Change-Id: Ia9f1d011ef28a9d62a3076fa497ebb33ed53fe0a
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index ba1c449..83a52b8 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -24,6 +24,7 @@
#include <android-base/unique_fd.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
+#include <binder/Stability.h>
#include <binder/TextOutput.h>
#include <binderdebug/BinderDebug.h>
#include <serviceutils/PriorityDumper.h>
@@ -69,12 +70,13 @@
" -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
" -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
" --pid: dump PID instead of usual dump\n"
- " --thread: dump thread usage instead of usual dump\n"
" --proto: filter services that support dumping data in proto format. Dumps\n"
" 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"
+ " --stability: dump binder stability information instead of usual dump\n"
+ " --thread: dump thread usage instead of usual dump\n"
" SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
}
@@ -128,12 +130,13 @@
Type type = Type::DUMP;
int timeoutArgMs = 10000;
int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
- static struct option longOptions[] = {{"thread", no_argument, 0, 0},
+ static struct option longOptions[] = {{"help", no_argument, 0, 0},
{"pid", no_argument, 0, 0},
{"priority", required_argument, 0, 0},
{"proto", no_argument, 0, 0},
{"skip", no_argument, 0, 0},
- {"help", no_argument, 0, 0},
+ {"stability", no_argument, 0, 0},
+ {"thread", no_argument, 0, 0},
{0, 0, 0, 0}};
// Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but
@@ -167,6 +170,8 @@
}
} else if (!strcmp(longOptions[optionIndex].name, "pid")) {
type = Type::PID;
+ } else if (!strcmp(longOptions[optionIndex].name, "stability")) {
+ type = Type::STABILITY;
} else if (!strcmp(longOptions[optionIndex].name, "thread")) {
type = Type::THREAD;
}
@@ -335,6 +340,11 @@
return OK;
}
+static status_t dumpStabilityToFd(const sp<IBinder>& service, const unique_fd& fd) {
+ WriteStringToFd(internal::Stability::debugToString(service) + "\n", fd);
+ return OK;
+}
+
static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) {
pid_t pid;
status_t status = service->getDebugPid(&pid);
@@ -382,6 +392,9 @@
case Type::PID:
err = dumpPidToFd(service, remote_end);
break;
+ case Type::STABILITY:
+ err = dumpStabilityToFd(service, remote_end);
+ break;
case Type::THREAD:
err = dumpThreadsToFd(service, remote_end);
break;
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 349947c..1b3ae6a 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -52,9 +52,10 @@
static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
enum class Type {
- DUMP, // dump using `dump` function
- PID, // dump pid of server only
- THREAD, // dump thread usage of server only
+ DUMP, // dump using `dump` function
+ PID, // dump pid of server only
+ STABILITY, // dump stability information of server
+ THREAD, // dump thread usage of server only
};
/**
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index c9d2dbb..277f445 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -582,6 +582,27 @@
AssertOutput(std::to_string(getpid()) + "\n");
}
+// Tests 'dumpsys --stability'
+TEST_F(DumpsysTest, ListAllServicesWithStability) {
+ ExpectListServices({"Locksmith", "Valet"});
+ ExpectCheckService("Locksmith");
+ ExpectCheckService("Valet");
+
+ CallMain({"--stability"});
+
+ AssertRunningServices({"Locksmith", "Valet"});
+ AssertOutputContains("stability");
+}
+
+// Tests 'dumpsys --stability service_name'
+TEST_F(DumpsysTest, ListServiceWithStability) {
+ ExpectCheckService("Locksmith");
+
+ CallMain({"--stability", "Locksmith"});
+
+ AssertOutputContains("stability");
+}
+
// Tests 'dumpsys --thread'
TEST_F(DumpsysTest, ListAllServicesWithThread) {
ExpectListServices({"Locksmith", "Valet"});
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 709cf67..601ce96 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -79,9 +79,9 @@
LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
}
-void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
+std::string Stability::debugToString(const sp<IBinder>& binder) {
auto stability = getCategory(binder.get());
- ALOGE("%s: stability is %s", tag.c_str(), stability.debugString().c_str());
+ return stability.debugString();
}
void Stability::markVndk(IBinder* binder) {
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index f4bfac8..6bc607f 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -100,7 +100,7 @@
static void markVintf(IBinder* binder);
// WARNING: for debugging only
- static void debugLogStability(const std::string& tag, const sp<IBinder>& binder);
+ static std::string debugToString(const sp<IBinder>& binder);
// WARNING: This is only ever expected to be called by auto-generated code or tests.
// You likely want to change or modify the stability of the interface you are using.
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 2ce13df..6c3b3d9 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -102,7 +102,7 @@
return Status::ok();
}
Status sendAndCallBinder(const sp<IBinder>& binder) override {
- Stability::debugLogStability("sendAndCallBinder got binder", binder);
+ ALOGI("Debug log stability: %s", Stability::debugToString(binder).c_str());
return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
}
Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
diff --git a/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
index 8b4ed70..371dcbd 100644
--- a/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
+++ b/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
@@ -31,37 +31,27 @@
static const std::vector<
std::function<void(FuzzedDataProvider*, android::sp<android::IBinder> const&)>>
gStabilityOperations = {
- // markCompilationUnit(IBinder* binder)
[](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
if (!marked) {
android::internal::Stability::markCompilationUnit(bbinder.get());
marked = true;
}
},
-
- // markVintf(IBinder* binder)
[](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
if (!marked) {
android::internal::Stability::markVintf(bbinder.get());
marked = true;
}
},
-
- // debugLogStability(const std::string& tag, const sp<IBinder>& binder)
- [](FuzzedDataProvider* fdp, android::sp<android::IBinder> const& bbinder) -> void {
- std::string tag = fdp->ConsumeRandomLengthString(STABILITY_MAX_TAG_LENGTH);
- android::internal::Stability::debugLogStability(tag, bbinder);
+ [](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
+ (void)android::internal::Stability::debugToString(bbinder);
},
-
- // markVndk(IBinder* binder)
[](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
if (!marked) {
android::internal::Stability::markVndk(bbinder.get());
marked = true;
}
},
-
- // requiresVintfDeclaration(const sp<IBinder>& binder)
[](FuzzedDataProvider*, android::sp<android::IBinder> const& bbinder) -> void {
android::internal::Stability::requiresVintfDeclaration(bbinder);
}};