Consolidate finally block of startActivityInner

The concept is similar to change
  if (c) fun1(); else fun3();
  if (c) fun2(); else fun4();
to
  if (c) {fun1(); fun2();} else {fun3(); fun4();}
So the logic for the same condition can be put together.

Besides, finally block should not be too large because compiler
just duplicates the entire block.

It is also better to put any operations that might change the
hierarchy before calling continueWindowLayout.

Also fix format and missing info of dumping ActivityStarter.

Bug: 163976519
Test: CtsActivityManagerDeviceTestCases

Change-Id: I8f6ca71fc9a13296fa391aef6656d533908adffb
This commit is contained in:
Riddle Hsu
2022-03-15 22:00:16 -06:00
parent 207a75d8d2
commit 14185cd0ee
2 changed files with 85 additions and 93 deletions

View File

@@ -544,10 +544,8 @@ public class ActivityStartController {
if (mLastHomeActivityStartRecord != null && (!dumpPackagePresent
|| dumpPackage.equals(mLastHomeActivityStartRecord.packageName))) {
if (!dumped) {
dumped = true;
dumpLastHomeActivityStartResult(pw, prefix);
}
dumped = true;
dumpLastHomeActivityStartResult(pw, prefix);
pw.print(prefix);
pw.println("mLastHomeActivityStartRecord:");
mLastHomeActivityStartRecord.dump(pw, prefix + " ", true /* dumpAll */);
@@ -565,6 +563,7 @@ public class ActivityStartController {
dumpLastHomeActivityStartResult(pw, prefix);
}
pw.print(prefix);
pw.println("mLastStarter:");
mLastStarter.dump(pw, prefix + " ");
if (dumpPackagePresent) {

View File

@@ -614,6 +614,9 @@ class ActivityStarter {
mVoiceInteractor = starter.mVoiceInteractor;
mIntentDelivered = starter.mIntentDelivered;
mLastStartActivityResult = starter.mLastStartActivityResult;
mLastStartActivityTimeMs = starter.mLastStartActivityTimeMs;
mLastStartReason = starter.mLastStartReason;
mRequest.set(starter.mRequest);
}
@@ -1599,7 +1602,6 @@ class ActivityStarter {
TaskFragment inTaskFragment, boolean restrictedBgActivity,
NeededUriGrants intentGrants) {
int result = START_CANCELED;
boolean startResultSuccessful = false;
final Task startedActivityRootTask;
// Create a transition now to record the original intent of actions taken within
@@ -1615,75 +1617,18 @@ class ActivityStarter {
newTransition.setRemoteTransition(remoteTransition);
}
transitionController.collect(r);
final boolean isTransient = r.getOptions() != null && r.getOptions().getTransientLaunch();
try {
mService.deferWindowLayout();
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
intentGrants);
startResultSuccessful = ActivityManager.isStartResultSuccessful(result);
final boolean taskAlwaysOnTop = options != null && options.getTaskAlwaysOnTop();
// Apply setAlwaysOnTop when starting an Activity is successful regardless of creating
// a new Activity or recycling the existing Activity.
if (taskAlwaysOnTop && startResultSuccessful) {
final Task targetRootTask =
mTargetRootTask != null ? mTargetRootTask : mTargetTask.getRootTask();
targetRootTask.setAlwaysOnTop(true);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
startedActivityRootTask = handleStartResult(r, result);
startedActivityRootTask = handleStartResult(r, options, result, newTransition,
remoteTransition);
mService.continueWindowLayout();
mSupervisor.mUserLeaving = false;
// Transition housekeeping
if (!startResultSuccessful) {
if (newTransition != null) {
newTransition.abort();
}
} else {
if (!mAvoidMoveToFront && mDoResume
&& mRootWindowContainer.hasVisibleWindowAboveButDoesNotOwnNotificationShade(
r.launchedFromUid)) {
// If the UID launching the activity has a visible window on top of the
// notification shade and it's launching an activity that's going to be at the
// front, we should move the shade out of the way so the user can see it.
// We want to avoid the case where the activity is launched on top of a
// background task which is not moved to the front.
StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
if (statusBar != null) {
// This results in a async call since the interface is one-way
statusBar.collapsePanels();
}
}
final boolean started = result == START_SUCCESS || result == START_TASK_TO_FRONT;
if (started) {
// The activity is started new rather than just brought forward, so record
// it as an existence change.
transitionController.collectExistenceChange(r);
} else if (result == START_DELIVERED_TO_TOP && newTransition != null) {
// We just delivered to top, so there isn't an actual transition here
newTransition.abort();
newTransition = null;
}
if (isTransient) {
// `r` isn't guaranteed to be the actual relevant activity, so we must wait
// until after we launched to identify the relevant activity.
transitionController.setTransientLaunch(mLastStartActivityRecord,
mPriorAboveTask);
}
if (newTransition != null) {
transitionController.requestStartTransition(newTransition,
mTargetTask == null ? r.getTask() : mTargetTask,
remoteTransition, null /* displayChange */);
} else if (started) {
// Make the collecting transition wait until this request is ready.
transitionController.setReady(r, false);
}
}
}
postStartActivityProcessing(r, result, startedActivityRootTask);
return result;
@@ -1695,40 +1640,89 @@ class ActivityStarter {
*
* @return the root task where the successful started activity resides.
*/
private @Nullable Task handleStartResult(@NonNull ActivityRecord started, int result) {
private @Nullable Task handleStartResult(@NonNull ActivityRecord started,
ActivityOptions options, int result, Transition newTransition,
RemoteTransition remoteTransition) {
mSupervisor.mUserLeaving = false;
final Task currentRootTask = started.getRootTask();
Task startedActivityRootTask = currentRootTask != null ? currentRootTask : mTargetRootTask;
final Task startedActivityRootTask =
currentRootTask != null ? currentRootTask : mTargetRootTask;
if (ActivityManager.isStartResultSuccessful(result)) {
if (startedActivityRootTask != null) {
// If there is no state change (e.g. a resumed activity is reparented to top of
// another display) to trigger a visibility/configuration checking, we have to
// update the configuration for changing to different display.
final ActivityRecord currentTop = startedActivityRootTask.topRunningActivity();
if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
mRootWindowContainer.ensureVisibilityAndConfig(
currentTop, currentTop.getDisplayId(),
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
if (!ActivityManager.isStartResultSuccessful(result) || startedActivityRootTask == null) {
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
if (mStartActivity.getTask() != null) {
mStartActivity.finishIfPossible("startActivity", true /* oomAdj */);
} else if (mStartActivity.getParent() != null) {
mStartActivity.getParent().removeChild(mStartActivity);
}
return startedActivityRootTask;
// Root task should also be detached from display and be removed if it's empty.
if (startedActivityRootTask != null && startedActivityRootTask.isAttached()
&& !startedActivityRootTask.hasActivity()
&& !startedActivityRootTask.isActivityTypeHome()) {
startedActivityRootTask.removeIfPossible("handleStartResult");
}
if (newTransition != null) {
newTransition.abort();
}
return null;
}
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
if (mStartActivity.getTask() != null) {
mStartActivity.finishIfPossible("startActivity", true /* oomAdj */);
} else if (mStartActivity.getParent() != null) {
mStartActivity.getParent().removeChild(mStartActivity);
// Apply setAlwaysOnTop when starting an activity is successful regardless of creating
// a new Activity or reusing the existing activity.
if (options != null && options.getTaskAlwaysOnTop()) {
startedActivityRootTask.setAlwaysOnTop(true);
}
// Root task should also be detached from display and be removed if it's empty.
if (startedActivityRootTask != null && startedActivityRootTask.isAttached()
&& !startedActivityRootTask.hasActivity()
&& !startedActivityRootTask.isActivityTypeHome()) {
startedActivityRootTask.removeIfPossible("handleStartResult");
startedActivityRootTask = null;
// If there is no state change (e.g. a resumed activity is reparented to top of
// another display) to trigger a visibility/configuration checking, we have to
// update the configuration for changing to different display.
final ActivityRecord currentTop = startedActivityRootTask.topRunningActivity();
if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
mRootWindowContainer.ensureVisibilityAndConfig(
currentTop, currentTop.getDisplayId(),
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
if (!mAvoidMoveToFront && mDoResume && mRootWindowContainer
.hasVisibleWindowAboveButDoesNotOwnNotificationShade(started.launchedFromUid)) {
// If the UID launching the activity has a visible window on top of the notification
// shade and it's launching an activity that's going to be at the front, we should move
// the shade out of the way so the user can see it. We want to avoid the case where the
// activity is launched on top of a background task which is not moved to the front.
final StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
if (statusBar != null) {
// This results in a async call since the interface is one-way.
statusBar.collapsePanels();
}
}
// Transition housekeeping.
final TransitionController transitionController = started.mTransitionController;
final boolean isStarted = result == START_SUCCESS || result == START_TASK_TO_FRONT;
if (isStarted) {
// The activity is started new rather than just brought forward, so record it as an
// existence change.
transitionController.collectExistenceChange(started);
} else if (result == START_DELIVERED_TO_TOP && newTransition != null) {
// We just delivered to top, so there isn't an actual transition here.
newTransition.abort();
newTransition = null;
}
if (options != null && options.getTransientLaunch()) {
// `started` isn't guaranteed to be the actual relevant activity, so we must wait
// until after we launched to identify the relevant activity.
transitionController.setTransientLaunch(mLastStartActivityRecord, mPriorAboveTask);
}
if (newTransition != null) {
transitionController.requestStartTransition(newTransition,
mTargetTask == null ? started.getTask() : mTargetTask,
remoteTransition, null /* displayChange */);
} else if (isStarted) {
// Make the collecting transition wait until this request is ready.
transitionController.setReady(started, false);
}
return startedActivityRootTask;
}
@@ -3169,7 +3163,6 @@ class ActivityStarter {
}
void dump(PrintWriter pw, String prefix) {
prefix = prefix + " ";
pw.print(prefix);
pw.print("mCurrentUser=");
pw.println(mRootWindowContainer.mCurrentUser);
@@ -3215,7 +3208,7 @@ class ActivityStarter {
pw.print(" mDoResume=");
pw.print(mDoResume);
pw.print(" mAddingToTask=");
pw.println(mAddingToTask);
pw.print(mAddingToTask);
pw.print(" mInTaskFragment=");
pw.println(mInTaskFragment);
}