Moved input time out handling to ActivityTaskManagerService (14/n)
Also:
- Post handling of scheduling GC from WM to AM side.
- Removed access on package manager through mAm reference.
Bug: 80414790
Test: Existing tests pass
Change-Id: Ia76c57411fc332ea099adb6ef7975e012b4d744c
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index ab1ba6c..4a0f692 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.BIND_VOICE_INTERACTION;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.Manifest.permission.FILTER_EVENTS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -36,15 +37,12 @@
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_NONE;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -74,7 +72,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IMMERSIVE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
@@ -122,6 +119,8 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
import android.os.IUserManager;
import android.os.PowerManager;
@@ -131,7 +130,6 @@
import android.os.WorkSource;
import android.view.WindowManager;
import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
import com.android.server.AppOpsService;
import com.android.server.pm.UserManagerService;
@@ -181,7 +179,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
-import android.os.Process;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.SystemClock;
@@ -250,6 +247,11 @@
private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
+ // How long we wait until we timeout on key dispatching.
+ private static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
+ // How long we wait until we timeout on key dispatching during instrumentation.
+ private static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
+
Context mContext;
/**
* This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can
@@ -261,6 +263,7 @@
ActivityManagerService mAm;
ActivityManagerInternal mAmInternal;
UriGrantsManagerInternal mUgmInternal;
+ private PackageManagerInternal mPmInternal;
/* Global service lock used by the package the owns this service. */
Object mGlobalLock;
ActivityStackSupervisor mStackSupervisor;
@@ -269,6 +272,8 @@
private AppOpsService mAppOpsService;
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
+ /** All processes we currently have running mapped by pid */
+ final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
/** This is the process holding what we currently consider to be the "home" activity. */
WindowProcessController mHomeProcess;
/**
@@ -4540,6 +4545,80 @@
&& mAmInternal.getCurrentUser().isDemo());
}
+ static long getInputDispatchingTimeoutLocked(ActivityRecord r) {
+ if (r == null || !r.hasProcess()) {
+ return KEY_DISPATCHING_TIMEOUT_MS;
+ }
+ return getInputDispatchingTimeoutLocked(r.app);
+ }
+
+ private static long getInputDispatchingTimeoutLocked(WindowProcessController r) {
+ if (r != null && (r.isInstrumenting() || r.isUsingWrapper())) {
+ return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
+ }
+ return KEY_DISPATCHING_TIMEOUT_MS;
+ }
+
+ long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+ if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission " + FILTER_EVENTS);
+ }
+ WindowProcessController proc;
+ long timeout;
+ synchronized (mGlobalLock) {
+ proc = mPidMap.get(pid);
+ timeout = getInputDispatchingTimeoutLocked(proc);
+ }
+
+ if (inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
+ return -1;
+ }
+
+ return timeout;
+ }
+
+ /**
+ * Handle input dispatching timeouts.
+ * Returns whether input dispatching should be aborted or not.
+ */
+ boolean inputDispatchingTimedOut(final WindowProcessController proc,
+ final ActivityRecord activity, final ActivityRecord parent,
+ final boolean aboveSystem, String reason) {
+ if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission " + FILTER_EVENTS);
+ }
+
+ final String annotation;
+ if (reason == null) {
+ annotation = "Input dispatching timed out";
+ } else {
+ annotation = "Input dispatching timed out (" + reason + ")";
+ }
+
+ if (proc != null) {
+ synchronized (mGlobalLock) {
+ if (proc.isDebugging()) {
+ return false;
+ }
+
+ if (proc.isInstrumenting()) {
+ Bundle info = new Bundle();
+ info.putString("shortMsg", "keyDispatchingTimedOut");
+ info.putString("longMsg", annotation);
+ mAm.finishInstrumentationLocked(
+ (ProcessRecord) proc.mOwner, Activity.RESULT_CANCELED, info);
+ return true;
+ }
+ }
+ mH.post(() -> {
+ mAm.mAppErrors.appNotResponding(
+ (ProcessRecord) proc.mOwner, activity, parent, aboveSystem, annotation);
+ });
+ }
+
+ return true;
+ }
+
/**
* Decide based on the configuration whether we should show the ANR,
* crash, etc dialogs. The idea is that if there is no affordance to
@@ -4784,6 +4863,26 @@
return kept;
}
+ void scheduleAppGcsLocked() {
+ mH.post(() -> mAmInternal.scheduleAppGcs());
+ }
+
+ /**
+ * Returns the PackageManager. Used by classes hosted by {@link ActivityTaskManagerService}. The
+ * PackageManager could be unavailable at construction time and therefore needs to be accessed
+ * on demand.
+ */
+ IPackageManager getPackageManager() {
+ return AppGlobals.getPackageManager();
+ }
+
+ PackageManagerInternal getPackageManagerInternalLocked() {
+ if (mPmInternal == null) {
+ mPmInternal = LocalServices.getService(PackageManagerInternal.class);
+ }
+ return mPmInternal;
+ }
+
void logAppTooSlow(WindowProcessController app, long startTime, String msg) {
if (true || Build.IS_USER) {
return;
@@ -5232,5 +5331,27 @@
}
}
}
+
+ @Override
+ public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason) {
+ synchronized (mGlobalLock) {
+ return ActivityTaskManagerService.this.inputDispatchingTimedOut(
+ pid, aboveSystem, reason);
+ }
+ }
+
+ @Override
+ public void onProcessMapped(int pid, WindowProcessController proc) {
+ synchronized (mGlobalLock) {
+ mPidMap.put(pid, proc);
+ }
+ }
+
+ @Override
+ public void onProcessUnMapped(int pid) {
+ synchronized (mGlobalLock) {
+ mPidMap.remove(pid);
+ }
+ }
}
}