Allow starting activity for result on another TaskFragment
...but still in the same Task. This is only possible when enabling ActivityEmbedding. Meanwhile, the result should be sent immediately if the result-to activity is in the RESUMED state. Bug: 253387076 Test: atest TaskFragmentTest ActivityRecordTests Change-Id: I9049e8cb2329836ac2661aa6ead679ffc838c3b8
This commit is contained in:
@@ -3317,9 +3317,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);
|
||||
}
|
||||
@@ -4630,7 +4638,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,
|
||||
|
||||
@@ -78,7 +78,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;
|
||||
|
||||
@@ -2777,11 +2776,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;
|
||||
}
|
||||
|
||||
@@ -172,13 +172,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
|
||||
@@ -189,7 +182,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 {}
|
||||
|
||||
@@ -616,14 +608,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1206,6 +1206,25 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFinishActivityIfPossible_sendResultImmediatelyIfResumed() {
|
||||
final Task task = new TaskBuilder(mSupervisor).build();
|
||||
final TaskFragment taskFragment1 = createTaskFragmentWithActivity(task);
|
||||
final TaskFragment taskFragment2 = createTaskFragmentWithActivity(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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -475,23 +472,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
|
||||
|
||||
Reference in New Issue
Block a user