Merge "Allow starting activity for result on another TaskFragment" into tm-qpr-dev am: c1108902cd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20554413

Change-Id: I9b3162c692096659c9489c5b3bff1f4e2c0133c0
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-12-03 04:24:26 +00:00
committed by Automerger Merge Worker
5 changed files with 31 additions and 46 deletions

View File

@@ -3327,9 +3327,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(resultGrants,
resultTo.getUriPermissionsLocked());
}
if (mForceSendResultForMediaProjection) {
resultTo.sendResult(this.getUid(), resultWho, requestCode, resultCode,
resultData, resultGrants, true /* forceSendForMediaProjection */);
if (mForceSendResultForMediaProjection || resultTo.isState(RESUMED)) {
// Sending the result to the resultTo activity asynchronously to prevent the
// resultTo activity getting results before this Activity paused.
final ActivityRecord resultToActivity = resultTo;
mAtmService.mH.post(() -> {
synchronized (mAtmService.mGlobalLock) {
resultToActivity.sendResult(this.getUid(), resultWho, requestCode,
resultCode, resultData, resultGrants,
mForceSendResultForMediaProjection);
}
});
} else {
resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
}
@@ -4640,7 +4648,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
false /* forceSendForMediaProjection */);
}
private void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
Intent data, NeededUriGrants dataGrants, boolean forceSendForMediaProjection) {
if (callingUid > 0) {
mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(dataGrants,

View File

@@ -80,7 +80,6 @@ import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -2799,11 +2798,6 @@ class ActivityStarter {
errMsg = "The app:" + mCallingUid + "is not trusted to " + mStartActivity;
break;
}
case EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT: {
errMsg = "Cannot embed activity across TaskFragments for result, resultTo: "
+ mStartActivity.resultTo;
break;
}
default:
errMsg = "Unhandled embed result:" + result;
}

View File

@@ -170,13 +170,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
* indicate that an Activity can't be embedded because the Activity is started on a new task.
*/
static final int EMBEDDING_DISALLOWED_NEW_TASK = 3;
/**
* An embedding check result of
* {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
* indicate that an Activity can't be embedded because the Activity is started on a new
* TaskFragment, e.g. start an Activity on a new TaskFragment for result.
*/
static final int EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT = 4;
/**
* Embedding check results of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
@@ -187,7 +180,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
EMBEDDING_DISALLOWED_UNTRUSTED_HOST,
EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION,
EMBEDDING_DISALLOWED_NEW_TASK,
EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT,
})
@interface EmbeddingCheckResult {}
@@ -614,14 +606,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
}
// Cannot embed activity across TaskFragments for activity result.
// If the activity that started for result is finishing, it's likely that this start mode
// is used to place an activity in the same task. Since the finishing activity won't be
// able to get the results, so it's OK to embed in a different TaskFragment.
if (a.resultTo != null && !a.resultTo.finishing && a.resultTo.getTaskFragment() != this) {
return EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
}
return EMBEDDING_ALLOWED;
}

View File

@@ -1206,6 +1206,25 @@ public class ActivityRecordTests extends WindowTestsBase {
}
}
@Test
public void testFinishActivityIfPossible_sendResultImmediatelyIfResumed() {
final Task task = new TaskBuilder(mSupervisor).build();
final TaskFragment taskFragment1 = createTaskFragmentWithParentTask(task);
final TaskFragment taskFragment2 = createTaskFragmentWithParentTask(task);
final ActivityRecord resultToActivity = taskFragment1.getTopMostActivity();
final ActivityRecord targetActivity = taskFragment2.getTopMostActivity();
resultToActivity.setState(RESUMED, "test");
targetActivity.setState(RESUMED, "test");
targetActivity.resultTo = resultToActivity;
clearInvocations(mAtm.getLifecycleManager());
targetActivity.finishIfPossible(0, new Intent(), null, "test", false /* oomAdj */);
waitUntilHandlersIdle();
verify(resultToActivity).sendResult(anyInt(), eq(null), anyInt(), anyInt(), any(), eq(null),
anyBoolean());
}
/**
* Verify that complete finish request for non-finishing activity is invalid.
*/

View File

@@ -24,7 +24,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.os.Process.FIRST_APPLICATION_UID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -33,9 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -477,23 +474,6 @@ public class TaskFragmentTest extends WindowTestsBase {
doReturn(true).when(taskFragment).smallerThanMinDimension(any());
assertEquals(EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION,
taskFragment.isAllowedToEmbedActivity(activity));
// Not allow to start activity across TaskFragments for result.
final TaskFragment newTaskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(taskFragment.getTask())
.build();
final ActivityRecord newActivity = new ActivityBuilder(mAtm)
.setUid(FIRST_APPLICATION_UID)
.build();
doReturn(true).when(newTaskFragment).isAllowedToEmbedActivityInTrustedMode(any(), anyInt());
doReturn(false).when(newTaskFragment).smallerThanMinDimension(any());
newActivity.resultTo = activity;
assertEquals(EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT,
newTaskFragment.isAllowedToEmbedActivity(newActivity));
// Allow embedding if the resultTo activity is finishing.
activity.finishing = true;
assertEquals(EMBEDDING_ALLOWED, newTaskFragment.isAllowedToEmbedActivity(newActivity));
}
@Test