From 46bb3e8a553cae4afd060efe04d08d1cc76183db Mon Sep 17 00:00:00 2001 From: Sanjana Sunil Date: Tue, 6 Dec 2022 14:53:48 +0000 Subject: [PATCH] Add a mainline-accessible API to kill an app on sandbox death This API can be accessed by mainline modules to kill a specific app process when its associated sandbox dies. It takes in the IBinder value of the corresponding IApplicationThread of the app to kill it. REASON_DEPENDENCY_DIED and SUBREASON_SDK_SANDBOX_DIED are used in the emitted AppProcessDied atom. Bug: 261558210 Test: atest SdkSandboxLifecycleHostTest Test: m statsd && statsd_testdrive 373 emits an atom with SUBREASON_SDK_SANDBOX_DIED Change-Id: Id37023eabaa5f734bb67bee07a0f779c355cc100 --- core/api/module-lib-current.txt | 1 + core/java/android/app/ApplicationExitInfo.java | 9 +++++++++ core/java/android/app/ContextImpl.java | 7 +++++++ core/java/android/content/Context.java | 12 ++++++++++++ core/java/android/content/ContextWrapper.java | 8 ++++++++ services/api/current.txt | 1 + .../android/server/am/ActivityManagerLocal.java | 10 ++++++++++ .../android/server/am/ActivityManagerService.java | 14 ++++++++++++++ 8 files changed, 62 insertions(+) diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 98c78fefcc600..2596d93b87c72 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -80,6 +80,7 @@ package android.content { } public abstract class Context { + method @NonNull public android.os.IBinder getIApplicationThreadBinder(); method @NonNull public android.os.UserHandle getUser(); field public static final String PAC_PROXY_SERVICE = "pac_proxy"; field public static final String TEST_NETWORK_SERVICE = "test_network"; diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java index 871d15ec0b405..51ea04f397d24 100644 --- a/core/java/android/app/ApplicationExitInfo.java +++ b/core/java/android/app/ApplicationExitInfo.java @@ -416,6 +416,15 @@ public final class ApplicationExitInfo implements Parcelable { */ public static final int SUBREASON_UNDELIVERED_BROADCAST = 26; + /** + * The process was killed because its associated SDK sandbox process (where it had loaded SDKs) + * had died; this would be set only when the reason is {@link #REASON_DEPENDENCY_DIED}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_SDK_SANDBOX_DIED = 27; + // If there is any OEM code which involves additional app kill reasons, it should // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000. diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 042bdd7e2ed57..afef124128da1 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1998,6 +1998,13 @@ class ContextImpl extends Context { return mMainThread.getApplicationThread(); } + /** @hide */ + @NonNull + @Override + public IBinder getIApplicationThreadBinder() { + return getIApplicationThread().asBinder(); + } + /** @hide */ @Override public Handler getMainThreadHandler() { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index df5a1ed661cd4..6d0b3bcadc605 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -7345,6 +7345,18 @@ public abstract class Context { throw new RuntimeException("Not implemented. Must override in a subclass."); } + /** + * Get the binder object associated with the IApplicationThread of this Context. + * + * This can be used by a mainline module to uniquely identify a specific app process. + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public IBinder getIApplicationThreadBinder() { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + /** * @hide */ diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index a1646a172521f..a4bb6cc491dec 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -1247,6 +1247,14 @@ public class ContextWrapper extends Context { return mBase.getIApplicationThread(); } + /** + * @hide + */ + @Override + public IBinder getIApplicationThreadBinder() { + return mBase.getIApplicationThreadBinder(); + } + /** * @hide */ diff --git a/services/api/current.txt b/services/api/current.txt index da5b1fcaae99f..5d3c88c08cd5e 100644 --- a/services/api/current.txt +++ b/services/api/current.txt @@ -40,6 +40,7 @@ package com.android.server.am { public interface ActivityManagerLocal { method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException; method public boolean canStartForegroundService(int, int, @NonNull String); + method public void killSdkSandboxClientAppProcess(@NonNull android.os.IBinder); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerLocal.java b/services/core/java/com/android/server/am/ActivityManagerLocal.java index 9f2cc7f9cb440..5175a31c16b51 100644 --- a/services/core/java/com/android/server/am/ActivityManagerLocal.java +++ b/services/core/java/com/android/server/am/ActivityManagerLocal.java @@ -23,6 +23,7 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.os.IBinder; import android.os.RemoteException; /** @@ -94,6 +95,15 @@ public interface ActivityManagerLocal { @Context.BindServiceFlags int flags) throws RemoteException; + /** + * Kill an app process associated with an SDK sandbox. + * + * @param clientApplicationThreadBinder binder value of the + * {@link android.app.IApplicationThread} of a client app process associated with a + * sandbox. This is obtained using {@link Context#getIApplicationThreadBinder()}. + */ + void killSdkSandboxClientAppProcess(@NonNull IBinder clientApplicationThreadBinder); + /** * Start a foreground service delegate. * @param options foreground service delegate options. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e7e20813cd321..316e0d5249b8f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -16939,6 +16939,20 @@ public class ActivityManagerService extends IActivityManager.Stub mContext.getOpPackageName(), UserHandle.getUserId(clientAppUid)) != 0; } + @Override + public void killSdkSandboxClientAppProcess(IBinder clientApplicationThreadBinder) { + synchronized (ActivityManagerService.this) { + ProcessRecord r = getRecordForAppLOSP(clientApplicationThreadBinder); + if (r != null) { + r.killLocked( + "sdk sandbox died", + ApplicationExitInfo.REASON_DEPENDENCY_DIED, + ApplicationExitInfo.SUBREASON_SDK_SANDBOX_DIED, + true); + } + } + } + @Override public void onUserRemoved(@UserIdInt int userId) { // Clean up any ActivityTaskManager state (by telling it the user is stopped)