From 6e130b154c74a7a967480b0c650a75111bc9b871 Mon Sep 17 00:00:00 2001 From: Will Burr Date: Wed, 16 Feb 2022 18:46:26 +0000 Subject: [PATCH] startProcessLocked: Inherit debuggable flag for SDK sandbox If the process is an SDK sandbox, we use the FLAG_DEBUGGABLE value of the associated app. This allows for attaching debugger to a sandbox (and their SDKs) when the app's manifest specifies android:debuggable is true. To achieve this, we add an isSdkSandbox property to the ProcessRecord which is read when the flags are being set. Bug: 210499058 Test: manual (1. load app with android:debuggable, 2. load SDK, 3. attach debugger in IntelliJ/Android Studio) Change-Id: Id0c6a5914aaabd6db28b562fe17d24396b462779 --- .../com/android/server/am/ProcessList.java | 27 ++++++++++++++++++- .../com/android/server/am/ProcessRecord.java | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 41cd61da022a0..5196f96a7969e 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -1903,7 +1903,13 @@ public final class ProcessList { uid = 0; } int runtimeFlags = 0; - if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + + boolean debuggableFlag = (app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + if (!debuggableFlag && app.isSdkSandbox) { + debuggableFlag = isAppForSdkSandboxDebuggable(app); + } + + if (debuggableFlag) { runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP; runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE; // Also turn on CheckJNI for debuggable apps. It's quite @@ -2072,6 +2078,25 @@ public final class ProcessList { } } + /** Return true if the client app for the SDK sandbox process is debuggable. */ + private boolean isAppForSdkSandboxDebuggable(ProcessRecord sandboxProcess) { + // TODO (b/221004701) use client app process name + final int appUid = Process.toAppUid(sandboxProcess.uid); + IPackageManager pm = mService.getPackageManager(); + try { + String[] packages = pm.getPackagesForUid(appUid); + for (String aPackage : packages) { + ApplicationInfo i = pm.getApplicationInfo(aPackage, 0, sandboxProcess.userId); + if ((i.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + return true; + } + } + } catch (RemoteException e) { + // shouldn't happen + } + return false; + } + @GuardedBy("mService") boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal, diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index be187e21db47d..c6195b4bef224 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -79,6 +79,7 @@ class ProcessRecord implements WindowProcessListener { volatile ApplicationInfo info; // all about the first app in the process final ProcessInfo processInfo; // if non-null, process-specific manifest info final boolean isolated; // true if this is a special isolated process + public final boolean isSdkSandbox; // true if this is an SDK sandbox process final boolean appZygote; // true if this is forked from the app zygote final int uid; // uid of process; may be different from 'info' if isolated final int userId; // user of process. @@ -514,6 +515,7 @@ class ProcessRecord implements WindowProcessListener { } processInfo = procInfo; isolated = Process.isIsolated(_uid); + isSdkSandbox = Process.isSdkSandboxUid(_uid); appZygote = (UserHandle.getAppId(_uid) >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID && UserHandle.getAppId(_uid) <= Process.LAST_APP_ZYGOTE_ISOLATED_UID); uid = _uid;