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
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 98c78fe..2596d93 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -80,6 +80,7 @@
}
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 871d15e..51ea04f 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -416,6 +416,15 @@
*/
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 042bdd7..afef1241 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1999,6 +1999,13 @@
}
/** @hide */
+ @NonNull
+ @Override
+ public IBinder getIApplicationThreadBinder() {
+ return getIApplicationThread().asBinder();
+ }
+
+ /** @hide */
@Override
public Handler getMainThreadHandler() {
return mMainThread.getHandler();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index df5a1ed..6d0b3bc 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -7346,6 +7346,18 @@
}
/**
+ * 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
*/
public Handler getMainThreadHandler() {
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index a1646a1..a4bb6cc 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1251,6 +1251,14 @@
* @hide
*/
@Override
+ public IBinder getIApplicationThreadBinder() {
+ return mBase.getIApplicationThreadBinder();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public Handler getMainThreadHandler() {
return mBase.getMainThreadHandler();
}
diff --git a/services/api/current.txt b/services/api/current.txt
index da5b1fc..5d3c88c 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -40,6 +40,7 @@
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 9f2cc7f..5175a31 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.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.os.IBinder;
import android.os.RemoteException;
/**
@@ -95,6 +96,15 @@
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.
* @param connection a service connection served as callback to caller.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e7e2081..316e0d5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16940,6 +16940,20 @@
}
@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)
mAtmInternal.onUserStopped(userId);