Activity启动流程(六)再次回到ActivityManagerService
发布日期:2021-07-23 22:22:29 浏览次数:2 分类:技术文章

本文共 22609 字,大约阅读时间需要 75 分钟。

上文插了一段Activity所在进程没有启动的情况

一:postExecute调用远端

下面继续看Activity启动过程,之前第四篇讲到Activity的pause

之前在TransactionExecutor类中讲到

lifecycleItem.execute(mTransactionHandler, token, mPendingActions);        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);

其中第一个方法是执行本地的onPause方法

尔当运行到第二个方法的时候,其实pause的一系列操作已经做完了

看下poseExecute方法

@Override    public void postExecute(ClientTransactionHandler client, IBinder token,            PendingTransactionActions pendingActions) {        if (mDontReport) {            return;        }        try {            // TODO(lifecycler): Use interface callback instead of AMS.            ActivityManager.getService().activityPaused(token);        } catch (RemoteException ex) {            throw ex.rethrowFromSystemServer();        }    }

这里其实又来了一次跨进程,这是9.0版本和其他版本的不同之处,

其他版本的通知远端pause已经完成都是在handlePauseActivity中完成的。

二.再次来到AMS

看下ams的activityPaused方法

@Override    public final void activityPaused(IBinder token) {        final long origId = Binder.clearCallingIdentity();        synchronized(this) {            ActivityStack stack = ActivityRecord.getStackLocked(token);            if (stack != null) {                stack.activityPausedLocked(token, false);            }        }        Binder.restoreCallingIdentity(origId);    }

然后来到ActivityStack类中的activityPausedLocked方法

final void activityPausedLocked(IBinder token, boolean timeout) {        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,            "Activity paused: token=" + token + ", timeout=" + timeout);        final ActivityRecord r = isInStackLocked(token);        if (r != null) {            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);            if (mPausingActivity == r) {                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r                        + (timeout ? " (due to timeout)" : " (pause complete)"));                mService.mWindowManager.deferSurfaceLayout();                try {                    completePauseLocked(true /* resumeNext */, null /* resumingActivity */);                } finally {                    mService.mWindowManager.continueSurfaceLayout();                }                return;            } else {                EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,                        r.userId, System.identityHashCode(r), r.shortComponentName,                        mPausingActivity != null                            ? mPausingActivity.shortComponentName : "(none)");                if (r.isState(PAUSING)) {                    r.setState(PAUSED, "activityPausedLocked");                    if (r.finishing) {                        if (DEBUG_PAUSE) Slog.v(TAG,                                "Executing finish of failed to pause activity: " + r);                        finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false,                                "activityPausedLocked");                    }                }            }        }        mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);    }

接着调用completePauseLockd方法

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {        ActivityRecord prev = mPausingActivity;        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);        if (prev != null) {            prev.setWillCloseOrEnterPip(false);            final boolean wasStopping = prev.isState(STOPPING);            prev.setState(PAUSED, "completePausedLocked");            if (prev.finishing) {                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,                        "completedPausedLocked");            } else if (prev.app != null) {                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev                        + " wasStopping=" + wasStopping + " visible=" + prev.visible);                if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,                            "Complete pause, no longer waiting: " + prev);                }                if (prev.deferRelaunchUntilPaused) {                    // Complete the deferred relaunch that was waiting for pause to complete.                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);                    prev.relaunchActivityLocked(false /* andResume */,                            prev.preserveWindowOnDeferredRelaunch);                } else if (wasStopping) {                    // We are also stopping, the stop request must have gone soon after the pause.                    // We can't clobber it, because the stop confirmation will not be handled.                    // We don't need to schedule another stop, we only need to let it happen.                    prev.setState(STOPPING, "completePausedLocked");                } else if (!prev.visible || shouldSleepOrShutDownActivities()) {                    // Clear out any deferred client hide we might currently have.                    prev.setDeferHidingClient(false);                    // If we were visible then resumeTopActivities will release resources before                    // stopping.                    addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);                }            } else {                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);                prev = null;            }            // It is possible the activity was freezing the screen before it was paused.            // In that case go ahead and remove the freeze this activity has on the screen            // since it is no longer visible.            if (prev != null) {                prev.stopFreezingScreenLocked(true /*force*/);            }            mPausingActivity = null;        }        if (resumeNext) {            final ActivityStack topStack = mStackSupervisor.getFocusedStack();            if (!topStack.shouldSleepOrShutDownActivities()) {                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);            } else {                checkReadyForSleep();                ActivityRecord top = topStack.topRunningActivityLocked();                if (top == null || (prev != null && top != prev)) {                    // If there are no more activities available to run, do resume anyway to start                    // something. Also if the top activity on the stack is not the just paused                    // activity, we need to go ahead and resume it to ensure we complete an                    // in-flight app switch.                    mStackSupervisor.resumeFocusedStackTopActivityLocked();                }            }        }        if (prev != null) {            prev.resumeKeyDispatchingLocked();            if (prev.app != null && prev.cpuTimeAtResume > 0                    && mService.mBatteryStatsService.isOnBattery()) {                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)                        - prev.cpuTimeAtResume;                if (diff > 0) {                    BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();                    synchronized (bsi) {                        BatteryStatsImpl.Uid.Proc ps =                                bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,                                        prev.info.packageName);                        if (ps != null) {                            ps.addForegroundTimeLocked(diff);                        }                    }                }            }            prev.cpuTimeAtResume = 0; // reset it        }        // Notify when the task stack has changed, but only if visibilities changed (not just        // focus). Also if there is an active pinned stack - we always want to notify it about        // task stack changes, because its positioning may depend on it.        if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause                || getDisplay().hasPinnedStack()) {            mService.mTaskChangeNotificationController.notifyTaskStackChanged();            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;        }        mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);    }

三:再次调用resumeFocusedStackTopActivityLocked

这里再次调用了、

 mStackSupervisor.resumeFocusedStackTopActivityLocked();

然后接着是ActivityStack的

resumeTopActivityUncheckedLocked

resumeTopActivityInnerLocked

这次在这里会执行(之前是startPausingLocked)

ActivityStackSupervisor的startSpecificActivityLocked 方法

然后是realStartActivityLocked

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,            boolean andResume, boolean checkConfig) throws RemoteException {        if (!allPausedActivitiesComplete()) {            // While there are activities pausing we skipping starting any new activities until            // pauses are complete. NOTE: that we also do this for activities that are starting in            // the paused state because they will first be resumed then paused on the client side.            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,                    "realStartActivityLocked: Skipping start of r=" + r                    + " some activities pausing...");            return false;        }        final TaskRecord task = r.getTask();        final ActivityStack stack = task.getStack();        beginDeferResume();        try {            r.startFreezingScreenLocked(app, 0);            // schedule launch ticks to collect information about slow apps.            r.startLaunchTickingLocked();            r.setProcess(app);            if (getKeyguardController().isKeyguardLocked()) {                r.notifyUnknownVisibilityLaunched();            }            // Have the window manager re-evaluate the orientation of the screen based on the new            // activity order.  Note that as a result of this, it can call back into the activity            // manager with a new orientation.  We don't care about that, because the activity is            // not currently running so we are just restarting it anyway.            if (checkConfig) {                // Deferring resume here because we're going to launch new activity shortly.                // We don't want to perform a redundant launch of the same record while ensuring                // configurations and trying to resume top activity of focused stack.                ensureVisibilityAndConfig(r, r.getDisplayId(),                        false /* markFrozenIfConfigChanged */, true /* deferResume */);            }            if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,                    true /* isTop */)) {                // We only set the visibility to true if the activity is allowed to be visible                // based on                // keyguard state. This avoids setting this into motion in window manager that is                // later cancelled due to later calls to ensure visible activities that set                // visibility back to false.                r.setVisibility(true);            }            final int applicationInfoUid =                    (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;            if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {                Slog.wtf(TAG,                        "User ID for activity changing for " + r                                + " appInfo.uid=" + r.appInfo.uid                                + " info.ai.uid=" + applicationInfoUid                                + " old=" + r.app + " new=" + app);            }            app.waitingToKill = null;            r.launchCount++;            r.lastLaunchTime = SystemClock.uptimeMillis();            if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);            int idx = app.activities.indexOf(r);            if (idx < 0) {                app.activities.add(r);            }            mService.updateLruProcessLocked(app, true, null);            mService.updateOomAdjLocked();            final LockTaskController lockTaskController = mService.getLockTaskController();            if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE                    || task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV                    || (task.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED                            && lockTaskController.getLockTaskModeState()                                    == LOCK_TASK_MODE_LOCKED)) {                lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);            }            try {                if (app.thread == null) {                    throw new RemoteException();                }                List
results = null; List
newIntents = null; if (andResume) { // We don't need to deliver new intents and/or set results if activity is going // to pause immediately after launch. results = r.results; newIntents = r.newIntents; } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Launching: " + r + " icicle=" + r.icicle + " with results=" + results + " newIntents=" + newIntents + " andResume=" + andResume); EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId, System.identityHashCode(r), task.taskId, r.shortComponentName); if (r.isActivityTypeHome()) { // Home process is the root process of the task. mService.mHomeProcess = task.mActivities.get(0).app; } mService.notifyPackageUse(r.intent.getComponent().getPackageName(), PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY); r.sleeping = false; r.forceNewConfig = false; mService.getAppWarningsLocked().onStartActivity(r); mService.showAskCompatModeDialogLocked(r); r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); ProfilerInfo profilerInfo = null; if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) { if (mService.mProfileProc == null || mService.mProfileProc == app) { mService.mProfileProc = app; ProfilerInfo profilerInfoSvc = mService.mProfilerInfo; if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) { if (profilerInfoSvc.profileFd != null) { try { profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup(); } catch (IOException e) { profilerInfoSvc.closeFd(); } } profilerInfo = new ProfilerInfo(profilerInfoSvc); } } } app.hasShownUi = true; app.pendingUiClean = true; app.forceProcessStateUpTo(mService.mTopProcessState); // Because we could be starting an Activity in the system process this may not go // across a Binder interface which would create a new Configuration. Consequently // we have to always create a new Configuration here. final MergedConfiguration mergedConfiguration = new MergedConfiguration( mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration()); r.setLastReportedConfiguration(mergedConfiguration); logIfTransactionTooLarge(r.intent, r.icicle); // Create activity launch transaction. final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken); clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, mService.isNextTransitionForward(), profilerInfo)); // Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 && mService.mHasHeavyWeightFeature) { // This may be a heavy-weight process! Note that the package // manager will ensure that only activity can run in the main // process of the .apk, which is the only thing that will be // considered heavy-weight. if (app.processName.equals(app.info.packageName)) { if (mService.mHeavyWeightProcess != null && mService.mHeavyWeightProcess != app) { Slog.w(TAG, "Starting new heavy weight process " + app + " when already running " + mService.mHeavyWeightProcess); } mService.mHeavyWeightProcess = app; Message msg = mService.mHandler.obtainMessage( ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG); msg.obj = r; mService.mHandler.sendMessage(msg); } } } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity // and give up. Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); mService.appDiedLocked(app); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } // This is the first time we failed -- restart process and // retry. r.launchFailed = true; app.activities.remove(r); throw e; } } finally { endDeferResume(); } r.launchFailed = false; if (stack.updateLRUListLocked(r)) { Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } // TODO(lifecycler): Resume or pause requests are done as part of launch transaction, // so updating the state should be done accordingly. if (andResume && readyToResume()) { // As part of the process of launching, ActivityThread also performs // a resume. stack.minimalResumeActivityLocked(r); } else { // This activity is not starting in the resumed state... which should look like we asked // it to pause+stop (but remain visible), and it has done so and reported back the // current icicle and other state. if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r + " (starting in paused state)"); r.setState(PAUSED, "realStartActivityLocked"); } // Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. if (isFocusedStack(stack)) { mService.getActivityStartController().startSetupActivity(); } // Update any services we are bound to that might care about whether // their client may have activities. if (r.app != null) { mService.mServices.updateServiceConnectionActivitiesLocked(r.app); } return true; }

这部分的关键方法在这里:

// Create activity launch transaction.                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,                        r.appToken);                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),                        System.identityHashCode(r), r.info,                        // TODO: Have this take the merged configuration instead of separate global                        // and override configs.                        mergedConfiguration.getGlobalConfiguration(),                        mergedConfiguration.getOverrideConfiguration(), r.compat,                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),                        profilerInfo));                // Set desired final state.                final ActivityLifecycleItem lifecycleItem;                if (andResume) {                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());                } else {                    lifecycleItem = PauseActivityItem.obtain();                }                clientTransaction.setLifecycleStateRequest(lifecycleItem);                // Schedule transaction.                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

  // Schedule transaction.

                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
到这里,远端的代码执行完了,下面又要再次回到本地

转载地址:https://blog.csdn.net/perfectnihil/article/details/91045773 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Activity启动流程(七)再次回到本地并执行handleLaunchActivity
下一篇:Activity启动流程(五)Activity所在进程启动过程及ActivityThread初始化

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月23日 12时46分05秒