From 1e2187cfea28d8d5057ad50e30756162982e9d05 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Thu, 15 Jul 2021 13:06:15 -0700 Subject: [PATCH] Add hidden ATM method to use in TaskFragmentOrganizer getActivityBelow() is necessary to check if a split rule should be applied for two activities on top of each other. This will only report an activity that belongs to the same process. When an application starts an activity B on top of an existing activity A normally, there might be a split rule to put them side-by-side. Organizer needs to know that activities A and B are on top of each other to check, so it can either intercept new activity launch or observe it after it happens and check the rules then. The second approach results in a cleaner implementation, but it also means that the organizer needs a reliable way to check which activity is directly below the launched one. There is no reliable source of info for that on the client side yet. Bug: 190433398 Bug: 190433500 Test: Manual, using the reference implementation of the organizer. Change-Id: I0e0116b1b0144e0ba4d19039d78c34495fbe4457 --- core/java/android/app/ActivityClient.java | 13 +++++++++++ .../app/IActivityClientController.aidl | 1 + .../server/wm/ActivityClientController.java | 22 +++++++++++++++++++ .../com/android/server/wm/ActivityRecord.java | 6 +++++ .../android/server/wm/ActivityStarter.java | 2 +- .../server/wm/ActivityTaskManagerService.java | 2 +- .../server/wm/RootWindowContainer.java | 5 ----- 7 files changed, 44 insertions(+), 7 deletions(-) diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index bd4386885dd65..2efdf51612c7e 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -16,6 +16,7 @@ package android.app; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Intent; import android.content.res.Configuration; @@ -205,6 +206,18 @@ public class ActivityClient { } } + /** + * Returns the activity token below in the same task if it belongs to the same process. + */ + @Nullable + public IBinder getActivityTokenBelow(IBinder activityToken) { + try { + return getActivityClientController().getActivityTokenBelow(activityToken); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + ComponentName getCallingActivity(IBinder token) { try { return getActivityClientController().getCallingActivity(token); diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index c6649692d848e..aba6eb9229f2d 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -70,6 +70,7 @@ interface IActivityClientController { boolean willActivityBeVisible(in IBinder token); int getDisplayId(in IBinder activityToken); int getTaskForActivity(in IBinder token, in boolean onlyRoot); + IBinder getActivityTokenBelow(IBinder token); ComponentName getCallingActivity(in IBinder token); String getCallingPackage(in IBinder token); int getLaunchedFromUid(in IBinder token); diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 8a76e3e586e01..97804d98781b8 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -42,6 +42,7 @@ import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH; import static com.android.server.wm.ActivityTaskManagerService.enforceNotIsolatedCaller; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -538,6 +539,27 @@ class ActivityClientController extends IActivityClientController.Stub { } } + @Override + @Nullable + public IBinder getActivityTokenBelow(IBinder activityToken) { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken); + if (ar == null) { + return null; + } + final ActivityRecord below = ar.getTask().getActivityBelow(ar); + if (below != null && below.getUid() == ar.getUid()) { + return below.appToken.asBinder(); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + return null; + } + @Override public ComponentName getCallingActivity(IBinder token) { synchronized (mGlobalLock) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 826022c0a6f21..84a3a7eb47817 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -6293,6 +6293,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return null; } + @Nullable + static ActivityRecord isInAnyTask(IBinder token) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + return (r != null && r.isAttached()) ? r : null; + } + /** * @return display id to which this record is attached, * {@link android.view.Display#INVALID_DISPLAY} if not attached. diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 9d127a6cd3ff1..f161f12579e48 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -872,7 +872,7 @@ class ActivityStarter { ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { - sourceRecord = mRootWindowContainer.isInAnyTask(resultTo); + sourceRecord = ActivityRecord.isInAnyTask(resultTo); if (DEBUG_RESULTS) { Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 02f1b8af3f59c..381d69571a96b 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -1540,7 +1540,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { sourceToken = resultTo; } - sourceRecord = mRootWindowContainer.isInAnyTask(sourceToken); + sourceRecord = ActivityRecord.isInAnyTask(sourceToken); if (sourceRecord == null) { throw new SecurityException("Called with bad activity token: " + sourceToken); } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index bad12b522bcbb..40324f7de7550 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -3524,11 +3524,6 @@ class RootWindowContainer extends WindowContainer return task; } - ActivityRecord isInAnyTask(IBinder token) { - final ActivityRecord r = ActivityRecord.forTokenLocked(token); - return (r != null && r.isDescendantOf(this)) ? r : null; - } - @VisibleForTesting void getRunningTasks(int maxNum, List list, int flags, int callingUid, ArraySet profileIds) {