二:Android S从桌面点击图标启动APP流程
Android 12的源码链接:Search
http://aospxref.com/android-12.0.0_r3/
点击桌面图标会进入Launcher应用的click方法中。
private static void onClick(View v) {// Make sure that rogue clicks don't get through while allapps is launching, or after the// view has detached (it's possible for this to happen if the view is removed mid touch).if (v.getWindowToken() == null) return;Launcher launcher = Launcher.getLauncher(v.getContext());if (!launcher.getWorkspace().isFinishedSwitchingState()) return;Object tag = v.getTag();if (tag instanceof WorkspaceItemInfo) {onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);} else if (tag instanceof FolderInfo) {if (v instanceof FolderIcon) {onClickFolderIcon(v);}} else if (tag instanceof AppInfo) {startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);} else if (tag instanceof LauncherAppWidgetInfo) {if (v instanceof PendingAppWidgetHostView) {onClickPendingWidget((PendingAppWidgetHostView) v, launcher);}} else if (tag instanceof SearchActionItemInfo) {onClickSearchAction(launcher, (SearchActionItemInfo) tag);}}
往下走
packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.javapublic static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {if (shortcut.isDisabled() && handleDisabledItemClicked(shortcut, launcher)) {return;}// Check for abandoned promiseif ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()) {String packageName = shortcut.getIntent().getComponent() != null? shortcut.getIntent().getComponent().getPackageName(): shortcut.getIntent().getPackage();if (!TextUtils.isEmpty(packageName)) {onClickPendingAppItem(v,launcher,packageName,(shortcut.runtimeStatusFlags& ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0);return;}}// Start activities
启动activitystartAppShortcutOrInfoActivity(v, shortcut, launcher);}
继而往下走
packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.javaprivate static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity");Intent intent;if (item instanceof ItemInfoWithIcon&& (((ItemInfoWithIcon) item).runtimeStatusFlags & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {//APP未在安装中ItemInfoWithIcon appInfo = (ItemInfoWithIcon) item;
根据点击的item解析出package nameintent = new PackageManagerHelper(launcher).getMarketIntent(appInfo.getTargetComponent().getPackageName());} else {
根据点击的item得到intentintent = item.getIntent();}if (intent == null) {throw new IllegalArgumentException("Input must have a valid intent");}if (item instanceof WorkspaceItemInfo) {WorkspaceItemInfo si = (WorkspaceItemInfo) item;if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)&& Intent.ACTION_VIEW.equals(intent.getAction())) {// make a copy of the intent that has the package set to null// we do this because the platform sometimes disables instant// apps temporarily (triggered by the user) and fallbacks to the// web ui. This only works though if the package isn't setintent = new Intent(intent);intent.setPackage(null);}}if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {// Preload the icon to reduce latency b/w swapping the floating view with the original.FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);}
将解析出的intent传入launcher.startActivitySafely(v, intent, item);}
继而会走入super的startActivitySafely
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java@Overridepublic boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
//判断是否已经resumedif (!hasBeenResumed()) {// Workaround an issue where the WM launch animation is clobbered when finishing the// recents animation into launcher. Defer launching the activity until Launcher is// next resumed.
解决当完成从最近任务动画进入launcher时WM启动动画被破坏的问题addOnResumeCallback(() -> startActivitySafely(v, intent, item));if (mOnDeferredActivityLaunchCallback != null) {mOnDeferredActivityLaunchCallback.run();mOnDeferredActivityLaunchCallback = null;}return true;}
进入super的startActivitySafelyboolean success = super.startActivitySafely(v, intent, item);if (success && v instanceof BubbleTextView) {// This is set to the view that launched the activity that navigated the user away// from launcher. Since there is no callback for when the activity has finished// launching, enable the press state and keep this reference to reset the press// state when we return to launcher.BubbleTextView btv = (BubbleTextView) v;btv.setStayPressed(true);addOnResumeCallback(() -> btv.setStayPressed(false));}return success;}
继承关系如下: public class Launcher extends StatefulActivityimplements LauncherExterns,Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener StatefulActivitypublic abstract class extends BaseState >extends BaseDraggingActivity
public abstract class BaseDraggingActivity extends BaseActivityimplements OnColorsChangedListener, DisplayInfoChangeListener
最终走入BaseDraggingActivity的startActivitySafely
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();return false;}
解析得到bundleBundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;UserHandle user = item == null ? null : item.user;// Prepare intent
添加FLAG_ACTIVITY_NEW_TASKintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);if (v != null) {intent.setSourceBounds(getViewBounds(v));}try {boolean isShortcut = (item instanceof WorkspaceItemInfo)&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)&& !((WorkspaceItemInfo) item).isPromise();if (isShortcut) {// Shortcuts need some special checks due to legacy reasons.startShortcutIntentSafely(intent, optsBundle, item);} else if (user == null || user.equals(Process.myUserHandle())) {// Could be launching some bookkeeping activity
启动activitystartActivity(intent, optsBundle);} else {getSystemService(LauncherApps.class).startMainActivity(intent.getComponent(), user, intent.getSourceBounds(), optsBundle);}if (item != null) {InstanceId instanceId = new InstanceIdSequence().newInstanceId();logAppLaunch(item, instanceId);}return true;} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);}return false;}
然后会调用基类的
frameworks/base/core/java/android/app/Activity.java中的
startActivityForResult方法
frameworks/base/core/java/android/app/Activity.java@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)&& mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {if (TextUtils.equals(getPackageName(),intent.resolveActivity(getPackageManager()).getPackageName())) {// Apply Autofill restore mechanism on the started activity by startActivity()final IBinder token =mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);// Remove restore ability from current activitymIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);// Put restore tokenintent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);}}if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}}
然后在当前类中继续往下走,调用startActivityForResult
frameworks/base/core/java/android/app/Activity.java@Override@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)public void startActivityForResult(String who, Intent intent, int requestCode, @Nullable Bundle options) {Uri referrer = onProvideReferrer();if (referrer != null) {intent.putExtra(Intent.EXTRA_REFERRER, referrer);}options = transferSpringboardActivityOptions(options);
通过Instrumentation跨进程启动activityInstrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, who,intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, who, requestCode,ar.getResultCode(), ar.getResultData());}cancelInputsAndStartExitTransition(options);}
然后走到了Instrumentation中,Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态,替换和修改类定义等。
frameworks/base/core/java/android/app/Instrumentation.java
frameworks/base/core/java/android/app/Instrumentation.javapublic ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;
...try {intent.migrateExtraStreamToClipData(who);intent.prepareToLeaveProcess(who);
获取ATMS的binder对象,通过对象调用startActivity方法int result = ActivityTaskManager.getService().startActivity(whoThread,who.getOpPackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}
然后走到了ActivityTaskManager中,通过AIDL获取到了ActivityTaskManagerService的实例
frameworks/base/core/java/android/app/ActivityTaskManager.java
frameworks/base/core/java/android/app/ActivityTaskManager.javapublic static IActivityTaskManager getService() {return IActivityTaskManagerSingleton.get();}@UnsupportedAppUsage(trackingBug = 129726065)private static final Singleton IActivityTaskManagerSingleton =new Singleton() {@Overrideprotected IActivityTaskManager create() {
获取ACTIVITY_TASK_SERVICE服务final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
返回Binder实例return IActivityTaskManager.Stub.asInterface(b);}};
------------------------------------------------------------------------------------------------------------------
从这里开始就走进入系统进程SystemServer中的ActivityTaskManagerService服务中。
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}@Overridepublic int startActivityAsUser(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions, int userId) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,true /*validateIncomingUser*/);}private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {assertPackageMatchesCallingUid(callingPackage);enforceNotIsolatedCaller("startActivityAsUser");userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
将相关设置参数等都设置进去
call:发起者context
callPackage:发起者包名// TODO: Switch to user app stacks here.return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId)
执行execute.execute();}
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private ActivityStartController mActivityStartController;ActivityStartController getActivityStartController() {return mActivityStartController;}ActivityStarter obtainStarter(Intent intent, String reason) {return mFactory.obtain().setIntent(intent).setReason(reason);
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Resolve necessary information according the request parameters provided earlier, and execute* the request which begin the journey of starting an activity.* @return The starter result.*/int execute() {
...res = resolveToHeavyWeightSwitcherIfNeeded();if (res != START_SUCCESS) {return res;}
res = executeRequest(mRequest);
...}
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Executing activity start request and starts the journey of starting an activity. Here* begins with performing several preliminary checks. The normally activity launch flow will* go through {@link #startActivityUnchecked} to {@link #startActivityInner}.*/private int executeRequest(Request request) {
...
//初始值
int err = ActivityManager.START_SUCCESS;
...
//根据各参数判断当前是否启动失败
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {// We couldn't find a class that can handle the given Intent.// That's the end of that!err = ActivityManager.START_INTENT_NOT_RESOLVED;}if (err == ActivityManager.START_SUCCESS && aInfo == null) {// We couldn't find the specific class specified in the Intent.// Also the end of the line.err = ActivityManager.START_CLASS_NOT_FOUND;}
...
//设置ActivityRecord的各种信息,ActivityRecord就代表一个activity,可通过ActivityRecord获取activity的各种信息
final ActivityRecord r = new ActivityRecord.Builder(mService).setCaller(callerApp).setLaunchedFromPid(callingPid).setLaunchedFromUid(callingUid).setLaunchedFromPackage(callingPackage).setLaunchedFromFeature(callingFeatureId).setIntent(intent).setResolvedType(resolvedType).setActivityInfo(aInfo).setConfiguration(mService.getGlobalConfiguration()).setResultTo(resultRecord).setResultWho(resultWho).setRequestCode(requestCode).setComponentSpecified(request.componentSpecified).setRootVoiceInteraction(voiceSession != null).setActivityOptions(checkedOptions).setSourceRecord(sourceRecord).build();
...
//启动activitymLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,restrictedBgActivity, intentGrants);
...
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Start an activity while most of preliminary checks has been done and caller has been* confirmed that holds necessary permissions to do so.* Here also ensures that the starting activity is removed if the start wasn't successful.*/private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,boolean restrictedBgActivity, NeededUriGrants intentGrants) {
...try {
//延迟绘制
mService.deferWindowLayout();Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
//start activity
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
} finally {Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);startedActivityRootTask = handleStartResult(r, result);
//continue绘制
mService.continueWindowLayout();
...
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Start an activity and determine if the activity should be adding to the top of an existing* task or delivered new intent to an existing activity. Also manipulating the activity task* onto requested or valid root-task/display.** Note: This method should only be called from {@link #startActivityUnchecked}.*/// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner@VisibleForTestingint startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) {setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor, restrictedBgActivity);computeLaunchingTaskFlags();computeSourceRootTask();mIntent.setFlags(mLaunchFlags);final Task reusedTask = getReusableTask();
...computeLaunchParams(r, sourceRecord, targetTask);
...mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,mKeepCurTransition, mOptions, sourceRecord);if (mDoResume) {final ActivityRecord topTaskActivity =mStartActivity.getTask().topRunningActivityLocked();if (!mTargetRootTask.isTopActivityFocusable()|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()&& mStartActivity != topTaskActivity)) {
//mTargetRootTask.ensureActivitiesVisible(null /* starting */,0 /* configChanges */, !PRESERVE_WINDOWS);
//mTargetRootTask.mDisplayContent.executeAppTransition();} else {
//if (mTargetRootTask.isTopActivityFocusable()&& !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {mTargetRootTask.moveToFront("startActivityInner");}
mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);}}mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);// Update the recent tasks list immediately when the activity startsmSupervisor.mRecentTasks.add(mStartActivity.getTask());mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);return START_SUCCESS;}
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedTasksTopActivities() {return resumeFocusedTasksTopActivities(null, null, null);}
----------------------------------------------------------------------------------boolean resumeFocusedTasksTopActivities(Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) {return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions,false /* deferPause */);}
----------------------------------------------------------------------------------boolean resumeFocusedTasksTopActivities(Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,boolean deferPause) { if (!mTaskSupervisor.readyToResume()) {return false;}boolean result = false;if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()|| getTopDisplayFocusedRootTask() == targetRootTask)) {result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,deferPause);}for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {final DisplayContent display = getChildAt(displayNdx);final boolean curResult = result;boolean[] resumedOnDisplay = new boolean[1];display.forAllRootTasks(rootTask -> {final ActivityRecord topRunningActivity = rootTask.topRunningActivity();if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {return;}if (rootTask == targetRootTask) {
//resumedOnDisplay[0] |= curResult;return;}if (rootTask.getDisplayArea().isTopRootTask(rootTask)&& topRunningActivity.isState(RESUMED)) {
//rootTask.executeAppTransition(targetOptions);} else {resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);}});result |= resumedOnDisplay[0];if (!resumedOnDisplay[0]) {
//final Task focusedRoot = display.getFocusedRootTask();if (focusedRoot != null) {
result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
} else if (targetRootTask == null) {result |= resumeHomeActivity(null /* prev */, "no-focusable-task",display.getDefaultTaskDisplayArea());}}}return result;}
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);}
----------------------------------------------------------------------------
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {if (mInResumeTopActivity) {// Don't even start recursing.return false;}boolean someActivityResumed = false;try {// Protect against recursion.mInResumeTopActivity = true;if (isLeafTask()) {if (isFocusableAndVisible()) {
//
someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
}} else {int idx = mChildren.size() - 1;while (idx >= 0) {final Task child = (Task) getChildAt(idx--);if (!child.isTopActivityFocusable()) {continue;}if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {break;}someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,deferPause);
//if (idx >= mChildren.size()) {idx = mChildren.size() - 1;}}}//final ActivityRecord next = topRunningActivity(true /* focusableOnly */);if (next == null || !next.canTurnScreenOn()) {checkReadyForSleep();}} finally {mInResumeTopActivity = false;}return someActivityResumed;}
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
@GuardedBy("mService")private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {
...ActivityRecord next = topRunningActivity(true /* focusableOnly */);final boolean hasRunningActivity = next != null;// TODO: Maybe this entire condition can get removed?if (hasRunningActivity && !isAttached()) {return false;}mRootWindowContainer.cancelInitializingActivities();if (!hasRunningActivity) {// There are no activities left in the root task, let's look somewhere else.return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);}next.delayedResume = false;final TaskDisplayArea taskDisplayArea = getDisplayArea();// If the top activity is the resumed one, nothing to do.if (mResumedActivity == next && next.isState(RESUMED)&& taskDisplayArea.allResumedActivitiesComplete()) {// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.executeAppTransition(options);// For devices that are not in fullscreen mode (e.g. freeform windows), it's possible// we still want to check if the visibility of other windows have changed (e.g. bringing// a fullscreen window forward to cover another freeform activity.)if (taskDisplayArea.inMultiWindowMode()) {taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,false /* preserveWindows */, true /* notifyClients */);}ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity "+ "resumed %s", next);return false;}if (!next.canResumeByCompat()) {return false;}// If we are currently pausing an activity, then don't do anything until that is done.final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();if (!allPausedComplete) {ProtoLog.v(WM_DEBUG_STATES,"resumeTopActivityLocked: Skip resume: some activity pausing.");return false;}// If we are sleeping, and there is no resumed activity, and the top activity is paused,// well that is the state we want.if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.executeAppTransition(options);ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Going to sleep and"+ " all paused");return false;}// Make sure that the user who owns this activity is started. If not,// we will just leave it as is because someone should be bringing// another user's activities to the top of the stack.if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {Slog.w(TAG, "Skipping resume of top activity " + next+ ": user " + next.mUserId + " is stopped");return false;}// The activity may be waiting for stop, but that is no longer// appropriate for it.mTaskSupervisor.mStoppingActivities.remove(next);if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);ActivityRecord lastResumed = null;final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTask()) {// So, why aren't we using prev here??? See the param comment on the method. prev// doesn't represent the last resumed activity. However, the last focus stack does if// it isn't null.lastResumed = lastFocusedRootTask.getResumedActivity();}boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);if (mResumedActivity != null) {ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);pausing |= startPausingLocked(false /* uiSleeping */, next,"resumeTopActivityInnerLocked");}if (pausing) {ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: Skip resume: need to"+ " start pausing");// At this point we want to put the upcoming activity's process// at the top of the LRU list, since we know we will be needing it// very soon and it would be a waste to let it get killed if it// happens to be sitting towards the end.if (next.attachedToProcess()) {next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,true /* activityChange */, false /* updateOomAdj */,false /* addPendingTopUid */);} else if (!next.isProcessRunning()) {// Since the start-process is asynchronous, if we already know the process of next// activity isn't running, we can start the process earlier to save the time to wait// for the current activity to be paused.final boolean isTop = this == taskDisplayArea.getFocusedRootTask();mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,isTop ? "pre-top-activity" : "pre-activity");}if (lastResumed != null) {lastResumed.setWillCloseOrEnterPip(true);}return true;} else if (mResumedActivity == next && next.isState(RESUMED)&& taskDisplayArea.allResumedActivitiesComplete()) {// It is possible for the activity to be resumed when we paused back stacks above if the// next activity doesn't have to wait for pause to complete.// So, nothing else to-do except:// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.executeAppTransition(options);ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity resumed "+ "(dontWaitForPause) %s", next);return true;}// If the most recent activity was noHistory but was only stopped rather// than stopped+finished because the device went to sleep, we need to make// sure to finish it as we're making a new activity topmost.if (shouldSleepActivities()) {mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);}if (prev != null && prev != next && next.nowVisible) {// The next activity is already visible, so hide the previous// activity's windows right now so we can show the new one ASAP.// We only do this if the previous is finishing, which should mean// it is on top of the one being resumed so hiding it quickly// is good. Otherwise, we want to do the normal route of allowing// the resumed activity to be shown so we can decide if the// previous should actually be hidden depending on whether the// new one is found to be full-screen or not.if (prev.finishing) {prev.setVisibility(false);if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,"Not waiting for visible to hide: " + prev+ ", nowVisible=" + next.nowVisible);} else {if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,"Previous already visible but still waiting to hide: " + prev+ ", nowVisible=" + next.nowVisible);}}// Launching this app's activity, make sure the app is no longer// considered stopped.try {mTaskSupervisor.getActivityMetricsLogger().notifyBeforePackageUnstopped(next.packageName);mAtmService.getPackageManager().setPackageStoppedState(next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */} catch (RemoteException e1) {} catch (IllegalArgumentException e) {Slog.w(TAG, "Failed trying to unstop package "+ next.packageName + ": " + e);}// We are starting up the next activity, so tell the window manager// that the previous one will be hidden soon. This way it can know// to ignore it when computing the desired screen orientation.boolean anim = true;final DisplayContent dc = taskDisplayArea.mDisplayContent;if (prev != null) {if (prev.finishing) {if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,"Prepare close transition: prev=" + prev);if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {anim = false;dc.prepareAppTransition(TRANSIT_NONE);} else {dc.prepareAppTransition(TRANSIT_CLOSE);}prev.setVisibility(false);} else {if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,"Prepare open transition: prev=" + prev);if (mTaskSupervisor.mNoAnimActivities.contains(next)) {anim = false;dc.prepareAppTransition(TRANSIT_NONE);} else {dc.prepareAppTransition(TRANSIT_OPEN,next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);}}} else {if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");if (mTaskSupervisor.mNoAnimActivities.contains(next)) {anim = false;dc.prepareAppTransition(TRANSIT_NONE);} else {dc.prepareAppTransition(TRANSIT_OPEN);}}if (anim) {next.applyOptionsAnimation();} else {next.abortAndClearOptionsAnimation();}mTaskSupervisor.mNoAnimActivities.clear();if (next.attachedToProcess()) {if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next+ " stopped=" + next.stopped+ " visibleRequested=" + next.mVisibleRequested);// If the previous activity is translucent, force a visibility update of// the next activity, so that it's added to WM's opening app list, and// transition animation can be set up properly.// For example, pressing Home button with a translucent activity in focus.// Launcher is already visible in this case. If we don't add it to opening// apps, maybeUpdateTransitToWallpaper() will fail to identify this as a// TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.final boolean lastActivityTranslucent = lastFocusedRootTask != null&& (lastFocusedRootTask.inMultiWindowMode()|| (lastFocusedRootTask.mLastPausedActivity != null&& !lastFocusedRootTask.mLastPausedActivity.occludesParent()));// This activity is now becoming visible.if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {next.setVisibility(true);}// schedule launch ticks to collect information about slow apps.next.startLaunchTickingLocked();ActivityRecord lastResumedActivity =lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity();final ActivityState lastState = next.getState();mAtmService.updateCpuStats();ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);next.setState(RESUMED, "resumeTopActivityInnerLocked");// Have the window manager re-evaluate the orientation of// the screen based on the new activity order.boolean notUpdated = true;// Activity should also be visible if set mLaunchTaskBehind to true (see// ActivityRecord#shouldBeVisibleIgnoringKeyguard()).if (shouldBeVisible(next)) {// We have special rotation behavior when here is some active activity that// requests specific orientation or Keyguard is locked. Make sure all activity// visibilities are set correctly as well as the transition is updated if needed// to get the correct rotation behavior. Otherwise the following call to update// the orientation may cause incorrect configurations delivered to client as a// result of invisible window resize.// TODO: Remove this once visibilities are set correctly immediately when// starting an activity.notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),true /* markFrozenIfConfigChanged */, false /* deferResume */);}if (notUpdated) {// The configuration update wasn't able to keep the existing// instance of the activity, and instead started a new one.// We should be all done, but let's just make sure our activity// is still at the top and schedule another run if something// weird happened.ActivityRecord nextNext = topRunningActivity();ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "+ "%s, new next: %s", next, nextNext);if (nextNext != next) {// Do over!mTaskSupervisor.scheduleResumeTopActivities();}if (!next.mVisibleRequested || next.stopped) {next.setVisibility(true);}next.completeResumeLocked();return true;}try {final ClientTransaction transaction =ClientTransaction.obtain(next.app.getThread(), next.appToken);// Deliver all pending results.ArrayList a = next.results;if (a != null) {final int N = a.size();if (!next.finishing && N > 0) {if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,"Delivering results to " + next + ": " + a);transaction.addCallback(ActivityResultItem.obtain(a));}}if (next.newIntents != null) {transaction.addCallback(NewIntentItem.obtain(next.newIntents, true /* resume */));}// Well the app will no longer be stopped.// Clear app token stopped state in window manager if needed.next.notifyAppResumed(next.stopped);EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),next.getTask().mTaskId, next.shortComponentName);mAtmService.getAppWarningsLocked().onResumeActivity(next);next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);next.abortAndClearOptionsAnimation();transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(next.app.getReportedProcState(),dc.isNextTransitionForward()));mAtmService.getLifecycleManager().scheduleTransaction(transaction);ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);} catch (Exception e) {// Whoops, need to restart this activity!ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "+ "%s", lastState, next);next.setState(lastState, "resumeTopActivityInnerLocked");// lastResumedActivity being non-null implies there is a lastStack present.if (lastResumedActivity != null) {lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");}Slog.i(TAG, "Restarting because process died: " + next);if (!next.hasBeenLaunched) {next.hasBeenLaunched = true;} else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null&& lastFocusedRootTask.isTopRootTaskInDisplayArea()) {next.showStartingWindow(false /* taskSwitch */);}mTaskSupervisor.startSpecificActivity(next, true, false);return true;}// From this point on, if something goes wrong there is no way// to recover the activity.try {next.completeResumeLocked();} catch (Exception e) {// If any exception gets thrown, toss away this// activity and try the next one.Slog.w(TAG, "Exception thrown during resume of " + next, e);next.finishIfPossible("resume-exception", true /* oomAdj */);return true;}} else {// Whoops, need to restart this activity!if (!next.hasBeenLaunched) {next.hasBeenLaunched = true;} else {if (SHOW_APP_STARTING_PREVIEW) {next.showStartingWindow(false /* taskSwich */);}if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);}ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Restarting %s", next);mTaskSupervisor.startSpecificActivity(next, true, true);}return true;}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
