Android6.0 AMS启动Activity(四) AMS内部一些成员变量

之前在分析AMS和ActivityStackSupervisor和ActivityStack对一些成员变量比较模糊,这篇博客主要讲下这些成员变量

一、AMS成员变量的初始化

我们先来看看AMS在systemServer的构造,初始化,先是调用了在SystemServiceManager中调用了AMS的构造函数。

        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

构造函数主要是初始化了一些成员变量,下面我们来看如下两个成员变量,mRecenTasks代表最近的几个task

        mRecentTasks = new RecentTasks(this);
        mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);

在ActivityStackSupervisor的构造函数就是创建了一个handler,然后把service和recentTasks保存在成员变量中。

    public ActivityStackSupervisor(ActivityManagerService service, RecentTasks recentTasks) {
        mService = service;
        mRecentTasks = recentTasks;
        mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
    }

随后在SystemServer中会调用如下代码,就是把SystemServer这个进程保存进程信息。

mActivityManagerService.setSystemProcess();

再后面我们看下如下代码,把WMS对象设置到AMS中去。

mActivityManagerService.setWindowManager(wm);

看下AMS的setWindowManager函数,保存了WMS,然后调用了ActivityStackSupervisor的setWindowManager函数。

    public void setWindowManager(WindowManagerService wm) {
        mWindowManager = wm;
        mStackSupervisor.setWindowManager(wm);
    }

看下ActivityStackSupervisor的setWindowManager函数,在这个函数中先获取所有的显示设备,然后一一对应创建ActivityDisplay对象,接着调用createStackOnDisplay对象创建获取displayId的ActivityContainer,在ActivityContainer中又创建了ActivitStack对象。

    void setWindowManager(WindowManagerService wm) {
        synchronized (mService) {
            mWindowManager = wm;

            mDisplayManager =
                    (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
            mDisplayManager.registerDisplayListener(this, null);

            Display[] displays = mDisplayManager.getDisplays();//获取所有的显示设备
            for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
                final int displayId = displays[displayNdx].getDisplayId();
                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);//每一个显示设备创建一个对象的ActivityDisplay
                if (activityDisplay.mDisplay == null) {
                    throw new IllegalStateException("Default Display does not exist");
                }
                mActivityDisplays.put(displayId, activityDisplay);
            }

            createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);//创建ActivityStack
            mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);

            mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);

            // Initialize this here, now that we can get a valid reference to PackageManager.
            mLeanbackOnlyDevice = isLeanbackOnlyDevice();
        }
    }

在createStackOnDisplay函数,会获取传入的displayId获取activityDisplay ,然后创建一个ActivityContainer在这个对象的构造函数中会创建一个ActivityStack对象,最后调用attachToDisplayLocked把这个activityDisplay和activityContainer 联系起来。

    ActivityStack createStackOnDisplay(int stackId, int displayId) {
        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
        if (activityDisplay == null) {
            return null;
        }

        ActivityContainer activityContainer = new ActivityContainer(stackId);
        mActivityContainers.put(stackId, activityContainer);//把activityContainer放入mActivityContainers中
        activityContainer.attachToDisplayLocked(activityDisplay);
        return activityContainer.mStack;
    }

我们再来看下ActivityContainer 的attachToDisplayLocked函数,ActivityStack的mStacks是每一个显示设备上所有的ActivityStack。

        void attachToDisplayLocked(ActivityDisplay activityDisplay) {
            if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this
                    + " to display=" + activityDisplay);
            mActivityDisplay = activityDisplay;
            mStack.mDisplayId = activityDisplay.mDisplayId;
            mStack.mStacks = activityDisplay.mStacks;

            activityDisplay.attachActivities(mStack);
            mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId);
        }

我们再来看ActivityDisplay的attachActivities函数,把当前的ActivityStack放在ActivityDisplay的mStacks中。

        void attachActivities(ActivityStack stack) {
            if (DEBUG_STACK) Slog.v(TAG_STACK,
                    "attachActivities: attaching " + stack + " to displayId=" + mDisplayId);
            mStacks.add(stack);
        }

所以每一个ActivityStack的mStacks变量代表的是这个显示设备上所有的ActivityStack。

然后我们再来看下面这句,调用getStack,传入的stackId就是HOME_STACK_ID,这样刚才创建的ActivityStack就赋给这些成员变量。这里mHomeStack就不会改变了,然后mFocusedStack和mLastFocusedStack会改变的。

mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);

二、startActivity流程

之前分析startActivity的时候,最后在ActivityStackSupervisor的startActivityUncheckedLocked函数分为两种情况,一种就是需要新建TaskRecord,另一种不需要新建TaskRecord。

2.1 需要创建新TaskRecord

现在我们再来看startActivity流程,回顾下在ActivityStackSupervisor的startActivityUncheckedLocked函数中,当需要创建一个新的task的时候,到如下代码线调用computeStackFocus函数创建了一个ActivityStack,然后调用ActivityStack的moveToFront函数

        if (r.resultTo == null && inTask == null && !addingToTask
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            targetStack = computeStackFocus(r, newTask);//创建ActivityStack
            targetStack.moveToFront("startingNewTask");//将当前的ActivityStack放在最前面

            if (reuseTask == null) {
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                        taskToAffiliate);
                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                        "Starting new activity " + r + " in new task " + r.task);
            } else {
                r.setTask(reuseTask, taskToAffiliate);
            }
            if (isLockTaskModeViolation(r.task)) {
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            if (!movedHome) {
                if ((launchFlags &
                        (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                    // Caller wants to appear on home activity, so before starting
                    // their own activity we will bring home to the front.
                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                }
            }
        }

我们先来看computeStackFocus函数,先是获取ActivityRecord的task对象,这个时候我们需要建一个task,所以显然为null。这个函数就是寻找合适的ActivityStack,最后没找到就调用createStackOnDisplay函数创建一个ActivityContainer对象,当然也就创建了ActivityStack对象了。

    ActivityStack computeStackFocus(ActivityRecord r, boolean newTask) {
        final TaskRecord task = r.task;//为null

        // On leanback only devices we should keep all activities in the same stack.
        if (!mLeanbackOnlyDevice &&
                (r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {

            ActivityStack stack;

            if (task != null && task.stack != null) {//如果当前TaskRecord中有stack,这里显然没有
                stack = task.stack;
                if (stack.isOnHomeDisplay()) {
                    if (mFocusedStack != stack) {
                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                                "computeStackFocus: Setting " + "focused stack to r=" + r
                                + " task=" + task);
                    } else {
                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                            "computeStackFocus: Focused stack already=" + mFocusedStack);
                    }
                }
                return stack;
            }

            final ActivityContainer container = r.mInitialActivityContainer;
            if (container != null) {
                // The first time put it on the desired stack, after this put on task stack.
                r.mInitialActivityContainer = null;
                return container.mStack;
            }

            if (mFocusedStack != mHomeStack && (!newTask ||//mFousedStack不是HomeStack,而且不是新建Task
                    mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                        "computeStackFocus: Have a focused stack=" + mFocusedStack);
                return mFocusedStack;
            }

            final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;//所有设备上的ActivityStack
            for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
                stack = homeDisplayStacks.get(stackNdx);
                if (!stack.isHomeStack()) {//如果StackId不是HOME_STACK_ID
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                            "computeStackFocus: Setting focused stack=" + stack);
                    return stack;
                }
            }

            // Need to create an app stack for this user.
            stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);//最后还是没找到创建一个ActivityContainer对象
            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
                    + r + " stackId=" + stack.mStackId);
            return stack;
        }
        return mHomeStack;
    }

然后我们再来看下ActivityStack的moveToFront函数,先看看当前是否是HOME_STACK_ID的Stack,如果不是将当前的stack放在mStacks的最前面。mStacks之前看过代表这个显示设备上所有的Stack.

    final void moveToFront(String reason) {
        if (isAttached()) {
            final boolean homeStack = isHomeStack()//看是否是HOME_STACK_ID的Stack
                    || (mActivityContainer.mParentActivity != null
                        && mActivityContainer.mParentActivity.isHomeActivity());
            ActivityStack lastFocusStack = null;
            if (!homeStack) {
                // Need to move this stack to the front before calling
                // {@link ActivityStackSupervisor#moveHomeStack} below.
                lastFocusStack = mStacks.get(mStacks.size() - 1);//获取最后的Stack
                mStacks.remove(this);//去除当前stack
                mStacks.add(this);//再加入,这样当前的stack就在最前面了
            }
            // TODO(multi-display): Focus stack currently adjusted in call to move home stack.
            // Needs to also work if focus is moving to the non-home display.
            if (isOnHomeDisplay()) {//是否是默认显示设备
                mStackSupervisor.moveHomeStack(homeStack, reason, lastFocusStack);
            }
            final TaskRecord task = topTask();
            if (task != null) {
                mWindowManager.moveTaskToTop(task.taskId);//通知wms
            }
        }
    }

我们再来看看ActivityStackSuperVisor的moveHomeStack函数,这里就是主要是赋值mLastFocusedStack 和 mFocusedStack 。mFocusedStack 就是上面函数刚刚放到mStacks中去的那个ActivityStack,mLastFocusedStack 就是上一个mStacks的最前面的ActivityStack。

    void moveHomeStack(boolean toFront, String reason, ActivityStack lastFocusedStack) {
        ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
        final int topNdx = stacks.size() - 1;
        if (topNdx <= 0) {
            return;
        }

        // The home stack should either be at the top or bottom of the stack list.
        if ((toFront && (stacks.get(topNdx) != mHomeStack))
                || (!toFront && (stacks.get(0) != mHomeStack))) {
            if (DEBUG_STACK) Slog.d(TAG_STACK, "moveHomeTask: topStack old="
                    + ((lastFocusedStack != null) ? lastFocusedStack : stacks.get(topNdx))
                    + " new=" + mFocusedStack);
            stacks.remove(mHomeStack);
            stacks.add(toFront ? topNdx : 0, mHomeStack);
        }

        if (lastFocusedStack != null) {
            mLastFocusedStack = lastFocusedStack;
        }
        mFocusedStack = stacks.get(topNdx);

再来继续看ActivityStackSupervisor的startActivityUncheckedLocked函数,接下来就是来创建TaskRecord。然后调用ActivityRecord的setTask,把这个创建了TaskRecord作为ActivityRecord的task对象。

            if (reuseTask == null) {
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                        taskToAffiliate);
                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                        "Starting new activity " + r + " in new task " + r.task);
            }

我们看ActivityStack的createTaskRecord函数,创建一个TaskRecord。然后调用addTask把TaskRecord保存下来。

    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            boolean toTop) {
        TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
                voiceInteractor);
        addTask(task, toTop, false);
        return task;
    }

addTask先把当前的ActivityStack放在这TaskRecord的stack成员变量中,然后就是把这个TaskRecord放在mTaskHistory一个合适的位置。

    void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
        task.stack = this;//把当前ActivityStack放在这TaskRecord的stack成员变量中
        if (toTop) {
            insertTaskAtTop(task, null);
        } else {
            mTaskHistory.add(0, task);
            updateTaskMovement(task, false);
        }
        if (!moving && task.voiceSession != null) {
            try {
                task.voiceSession.taskStarted(task.intent, task.taskId);
            } catch (RemoteException e) {
            }
        }
    }

2.2 不需要新建TaskReocrd

我们还是看下ActivityStackSupervisor的startActivityUncheckedLocked函数,下面是不要创建新的TaskReocrd的流程。先直接从ActivityRecord的task获取TaskRecord对象。

然后从TaskRecord的stack获取ActivityStack对象。和上面流程一样,先调用ActivityStack的moveToFront将当前这个ActivityStack放在最前面,同时改变mFocusedStack和mLastFocusedStack的值。然后又看当前这个TaskRecord是否是当前ActivityStack最前面的。如果不是把它调整到最前面

        } else if (sourceRecord != null) {
            final TaskRecord sourceTask = sourceRecord.task;
            if (isLockTaskModeViolation(sourceTask)) {
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            targetStack = sourceTask.stack;
            targetStack.moveToFront("sourceStackToFront");//把当前ActivityStack放在最前面
            final TaskRecord topTask = targetStack.topTask();
            if (topTask != sourceTask) {
                targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,//把当前TaskRecord放在ActivityStack的最前面
                        r.appTimeTracker, "sourceTaskToFront");
            }

三、将Activity放在TaskRecord的最前面

下面我们再来看ActivityStack的startActivityLocked函数有下面代码,会把当前要启动的Activity放在TaskRecord的最前面

        task = r.task;

        // Slot the activity into the history stack and proceed
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        task.addActivityToTop(r);
        task.setFrontOfTask();

四、保存TaskRecord到mRecentTasks

我们继续分析ActivityStatck的resumeTopActivityInnerLocked函数,先分析要启动的Activity已经有进程了,这里我会先调用mRecentTasks.addLocked把现在的TaskRecord保存在mRecentTasks代表最近启动的Task

        if (next.app != null && next.app.thread != null) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);

            // This activity is now becoming visible.
            mWindowManager.setAppVisibility(next.appToken, true);

            // schedule launch ticks to collect information about slow apps.
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastStack == null ? null :lastStack.mResumedActivity;
            ActivityState lastState = next.state;

            mService.updateCpuStats();

            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
            next.state = ActivityState.RESUMED;
            mResumedActivity = next;
            next.task.touchActiveTime();
            mRecentTasks.addLocked(next.task);//保存TaskRecord在mRecentTasks
            mService.updateLruProcessLocked(next.app, true, null);
            updateLRUListLocked(next);
            mService.updateOomAdjLocked();
            ......

            try {
                // Deliver all pending results.
                ArrayList<ResultInfo> 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);
                        next.app.thread.scheduleSendResult(next.appToken, a);
                    }
                }
                ......
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,//调用ActivityThread的函数
                        mService.isNextTransitionForward(), resumeAnimOptions);

那如果启动没有进程的Activity又是在哪保存TaskRecord到mRecentTasks的呢。如果没有进程会调用startSpecificActivityLocked函数,最后又到ActivityThread的main函数,又调用AMS的attachApplicationLocked函数。在AMS的attachApplicationLocked函数中又会调用ActivityStackSupervisor的attachApplicationLocked方法。

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

在ActivityStackSupervisor的attachApplicationLocked方法中又调用了realStartActivityLocked方法,在realStartActivityLocked方法中会调用app.thread.scheduleLaunchActivity启动Activity,后面还会调用ActivityStac的minimalResumeActivityLocked方法。

在这个函数中调用了mRecentTasks.addLocked方法保存了TaskRecord,还保存了mResumedActivity。

    void minimalResumeActivityLocked(ActivityRecord r) {
        r.state = ActivityState.RESUMED;
        if (DEBUG_STATES) Slog.v(TAG_STATES,
                "Moving to RESUMED: " + r + " (starting new instance)");
        r.stopped = false;
        mResumedActivity = r;
        r.task.touchActiveTime();
        mRecentTasks.addLocked(r.task);
        completeResumeLocked(r);
        mStackSupervisor.checkReadyForSleepLocked();
        setLaunchTime(r);
        if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
                "Launch completed; removing icicle of " + r.icicle);
    }



    原文作者:kc专栏
    原文地址: https://blog.csdn.net/kc58236582/article/details/52484432
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞