Merge "Launch all activities into the same display" into tm-qpr-dev

This commit is contained in:
Xu Cao
2022-09-12 14:19:54 +00:00
committed by Android (Google) Code Review
3 changed files with 57 additions and 1 deletions

View File

@@ -384,6 +384,14 @@ public class ActivityStartController {
callingUid, realCallingUid, UserHandle.USER_NULL);
final SparseArray<String> startingUidPkgs = new SparseArray<>();
final long origId = Binder.clearCallingIdentity();
SafeActivityOptions bottomOptions = null;
if (options != null) {
// To ensure the first N-1 activities (N == total # of activities) are also launched
// into the correct display, use a copy of the passed-in options (keeping only
// display-related info) for these activities.
bottomOptions = options.selectiveCloneDisplayOptions();
}
try {
intents = ArrayUtils.filterNotNull(intents, Intent[]::new);
final ActivityStarter[] starters = new ActivityStarter[intents.length];
@@ -432,7 +440,7 @@ public class ActivityStartController {
final boolean top = i == intents.length - 1;
final SafeActivityOptions checkedOptions = top
? options
: null;
: bottomOptions;
starters[i] = obtainStarter(intent, reason)
.setIntentGrants(intentGrants)
.setCaller(caller)

View File

@@ -115,6 +115,34 @@ public class SafeActivityOptions {
mOriginalOptions = options;
}
/**
* To ensure that two activities, one using this object, and the other using the
* SafeActivityOptions returned from this function, are launched into the same display through
* ActivityStartController#startActivities, all display-related information, i.e.
* displayAreaToken, launchDisplayId and callerDisplayId, are cloned.
*/
@Nullable SafeActivityOptions selectiveCloneDisplayOptions() {
final ActivityOptions options = cloneLaunchingDisplayOptions(mOriginalOptions);
final ActivityOptions callerOptions = cloneLaunchingDisplayOptions(mCallerOptions);
if (options == null && callerOptions == null) {
return null;
}
final SafeActivityOptions safeOptions = new SafeActivityOptions(options,
mOriginalCallingPid, mOriginalCallingUid);
safeOptions.mCallerOptions = callerOptions;
safeOptions.mRealCallingPid = mRealCallingPid;
safeOptions.mRealCallingUid = mRealCallingUid;
return safeOptions;
}
private ActivityOptions cloneLaunchingDisplayOptions(ActivityOptions options) {
return options == null ? null : ActivityOptions.makeBasic()
.setLaunchTaskDisplayArea(options.getLaunchTaskDisplayArea())
.setLaunchDisplayId(options.getLaunchDisplayId())
.setCallerDisplayId((options.getCallerDisplayId()));
}
/**
* Overrides options with options from a caller and records {@link Binder#getCallingPid}/
* {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when calling this

View File

@@ -17,9 +17,12 @@
package com.android.server.wm;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
import android.app.ActivityOptions;
import android.platform.test.annotations.Presubmit;
import android.window.WindowContainerToken;
import androidx.test.filters.MediumTest;
@@ -43,4 +46,21 @@ public class SafeActivityOptionsTest {
final ActivityOptions result = options.mergeActivityOptions(opts1, opts2);
assertEquals(6, result.getLaunchDisplayId());
}
@Test
public void test_selectiveCloneDisplayOptions() {
final WindowContainerToken token = mock(WindowContainerToken.class);
final int launchDisplayId = 5;
final int callerDisplayId = 6;
final SafeActivityOptions clone = new SafeActivityOptions(ActivityOptions.makeBasic()
.setLaunchTaskDisplayArea(token)
.setLaunchDisplayId(launchDisplayId)
.setCallerDisplayId(callerDisplayId))
.selectiveCloneDisplayOptions();
assertSame(clone.getOriginalOptions().getLaunchTaskDisplayArea(), token);
assertEquals(clone.getOriginalOptions().getLaunchDisplayId(), launchDisplayId);
assertEquals(clone.getOriginalOptions().getCallerDisplayId(), callerDisplayId);
}
}