Dumpsys support for IncrementalService.
Test: atest PackageManagerShellCommandTest
Test: adb shell dumpsys incremental
Bug: b/136132412 b/133435829
Change-Id: I8a91eddb850c68da87f56a82ca14fdf9ac5d3ce5
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index 5876d43..64f25dd 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -32,7 +32,10 @@
import android.os.incremental.IIncrementalManager;
import android.util.Slog;
+import com.android.internal.util.DumpUtils;
+
import java.io.FileDescriptor;
+import java.io.PrintWriter;
/**
* This service has the following purposes:
@@ -71,6 +74,13 @@
mNativeInstance = nativeStartService();
}
+ @SuppressWarnings("resource")
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
+ nativeDump(mNativeInstance, fd.getInt$());
+ }
+
/**
* Notifies native IIncrementalManager service that system is ready.
*/
@@ -158,4 +168,6 @@
private static native long nativeStartService();
private static native void nativeSystemReady(long nativeInstance);
+
+ private static native void nativeDump(long nativeInstance, int fd);
}
diff --git a/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp b/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp
index 5e255f4..10bac94 100644
--- a/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp
+++ b/services/core/jni/com_android_server_incremental_IncrementalManagerService.cpp
@@ -33,9 +33,14 @@
Incremental_IncrementalService_OnSystemReady(self);
}
+static void nativeDump(JNIEnv* env, jclass klass, jlong self, jint fd) {
+ Incremental_IncrementalService_OnDump(self, fd);
+}
+
static const JNINativeMethod method_table[] = {
{"nativeStartService", "()J", (void*)nativeStartService},
{"nativeSystemReady", "(J)V", (void*)nativeSystemReady},
+ {"nativeDump", "(JI)V", (void*)nativeDump},
};
int register_android_server_incremental_IncrementalManagerService(JNIEnv* env) {
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 91d0572..0941831 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -17,12 +17,14 @@
#include "BinderIncrementalService.h"
#include <binder/IResultReceiver.h>
+#include <binder/PermissionCache.h>
#include <incfs.h>
#include "ServiceWrappers.h"
#include "jni.h"
#include "nativehelper/JNIHelp.h"
#include "path.h"
+#include <android-base/logging.h>
using namespace std::literals;
using namespace android::incremental;
@@ -90,8 +92,13 @@
return self.get();
}
-status_t BinderIncrementalService::dump(int fd, const Vector<String16>& args) {
- return OK;
+status_t BinderIncrementalService::dump(int fd, const Vector<String16>&) {
+ static const String16 kDump("android.permission.DUMP");
+ if (!PermissionCache::checkCallingPermission(kDump)) {
+ return PERMISSION_DENIED;
+ }
+ mImpl.onDump(fd);
+ return NO_ERROR;
}
void BinderIncrementalService::onSystemReady() {
@@ -280,3 +287,10 @@
((android::os::incremental::BinderIncrementalService*)self)->onSystemReady();
}
}
+void Incremental_IncrementalService_OnDump(jlong self, jint fd) {
+ if (self) {
+ ((android::os::incremental::BinderIncrementalService*)self)->dump(fd, {});
+ } else {
+ dprintf(fd, "BinderIncrementalService is stopped.");
+ }
+}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index e4a37dde..12713e8 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -35,6 +35,7 @@
#include <uuid/uuid.h>
#include <zlib.h>
+#include <ctime>
#include <iterator>
#include <span>
#include <stack>
@@ -256,6 +257,68 @@
IncrementalService::~IncrementalService() = default;
+inline const char* toString(TimePoint t) {
+ using SystemClock = std::chrono::system_clock;
+ time_t time = SystemClock::to_time_t(SystemClock::now() + std::chrono::duration_cast<SystemClock::duration>(t - Clock::now()));
+ return std::ctime(&time);
+}
+
+inline const char* toString(IncrementalService::BindKind kind) {
+ switch (kind) {
+ case IncrementalService::BindKind::Temporary:
+ return "Temporary";
+ case IncrementalService::BindKind::Permanent:
+ return "Permanent";
+ }
+}
+
+void IncrementalService::onDump(int fd) {
+ dprintf(fd, "Incremental is %s\n", incfs::enabled() ? "ENABLED" : "DISABLED");
+ dprintf(fd, "Incremental dir: %s\n", mIncrementalDir.c_str());
+
+ std::unique_lock l(mLock);
+
+ dprintf(fd, "Mounts (%d):\n", int(mMounts.size()));
+ for (auto&& [id, ifs] : mMounts) {
+ const IncFsMount& mnt = *ifs.get();
+ dprintf(fd, "\t[%d]:\n", id);
+ dprintf(fd, "\t\tmountId: %d\n", mnt.mountId);
+ dprintf(fd, "\t\tnextStorageDirNo: %d\n", mnt.nextStorageDirNo.load());
+ dprintf(fd, "\t\tdataLoaderStatus: %d\n", mnt.dataLoaderStatus.load());
+ dprintf(fd, "\t\tconnectionLostTime: %s\n", toString(mnt.connectionLostTime));
+ if (mnt.savedDataLoaderParams) {
+ const auto& params = mnt.savedDataLoaderParams.value();
+ dprintf(fd, "\t\tsavedDataLoaderParams:\n");
+ dprintf(fd, "\t\t\ttype: %s\n", toString(params.type).c_str());
+ dprintf(fd, "\t\t\tpackageName: %s\n", params.packageName.c_str());
+ dprintf(fd, "\t\t\tclassName: %s\n", params.className.c_str());
+ dprintf(fd, "\t\t\targuments: %s\n", params.arguments.c_str());
+ dprintf(fd, "\t\t\tdynamicArgs: %d\n", int(params.dynamicArgs.size()));
+ }
+ dprintf(fd, "\t\tstorages (%d):\n", int(mnt.storages.size()));
+ for (auto&& [storageId, storage] : mnt.storages) {
+ dprintf(fd, "\t\t\t[%d] -> [%s]\n", storageId, storage.name.c_str());
+ }
+
+ dprintf(fd, "\t\tbindPoints (%d):\n", int(mnt.bindPoints.size()));
+ for (auto&& [target, bind] : mnt.bindPoints) {
+ dprintf(fd, "\t\t\t[%s]->[%d]:\n", target.c_str(), bind.storage);
+ dprintf(fd, "\t\t\t\tsavedFilename: %s\n", bind.savedFilename.c_str());
+ dprintf(fd, "\t\t\t\tsourceDir: %s\n", bind.sourceDir.c_str());
+ dprintf(fd, "\t\t\t\tkind: %s\n", toString(bind.kind));
+ }
+ }
+
+ dprintf(fd, "Sorted binds (%d):\n", int(mBindsByPath.size()));
+ for (auto&& [target, mountPairIt] : mBindsByPath) {
+ const auto& bind = mountPairIt->second;
+ dprintf(fd, "\t\t[%s]->[%d]:\n", target.c_str(), bind.storage);
+ dprintf(fd, "\t\t\tsavedFilename: %s\n", bind.savedFilename.c_str());
+ dprintf(fd, "\t\t\tsourceDir: %s\n", bind.sourceDir.c_str());
+ dprintf(fd, "\t\t\tkind: %s\n", toString(bind.kind));
+ }
+}
+
std::optional<std::future<void>> IncrementalService::onSystemReady() {
std::promise<void> threadFinished;
if (mSystemReady.exchange(true)) {
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index ca5e4db..8280287 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -90,6 +90,8 @@
return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
}
+ void onDump(int fd);
+
std::optional<std::future<void>> onSystemReady();
StorageId createStorage(std::string_view mountPoint,
diff --git a/services/incremental/include/incremental_service.h b/services/incremental/include/incremental_service.h
index 7109d95..4a34b11 100644
--- a/services/incremental/include/incremental_service.h
+++ b/services/incremental/include/incremental_service.h
@@ -26,6 +26,7 @@
jlong Incremental_IncrementalService_Start();
void Incremental_IncrementalService_OnSystemReady(jlong self);
+void Incremental_IncrementalService_OnDump(jlong self, jint fd);
__END_DECLS