美文网首页
从LaunchMode看Android Activity的启动

从LaunchMode看Android Activity的启动

作者: lbtrace | 来源:发表于2017-11-18 14:01 被阅读66次

    本文基于Android 7.0源码分析

    Activity的启动模式

    在介绍Activity的启动模式之前先介绍下System管理Activity的核心类。

    ActivityRecord为Activity组件在System侧的代表。

    • service: System中的ActivityManagerService
    • appToken: 窗口管理标记
    • info: Activity组件信息
    • appInfo: Activity组件宿主应用的信息
    • processName: Activity宿主进程名
    • task: Activity所在的Task
    • resultTo: 启动Activity的Source ActivityRecord
    • app: Activity宿主进程记录
    • state: Activity组件的状态
    • icicle: 用于保存Activity先前的状态
    • launchMode: Activity的启动模式
    • mStartingWindowState: StartingWindow的状态

    TaskRecord

    TaskRecord描述在执行特定作业时与用户交互的一系列Activity,在TaskRecord中以栈的方式管理其中的Activity。

    • mActivities: TaskRecord中的一系列Activity
    • stack: TaskRecord所属的ActivityStack

    ActivityStack

    管理一组TaskRecord,在ActivityStack中不以栈的方式管理TaskRecord。

    • mTaskHistory: ActivityStack中的一系列TaskRecord
    • mLRUActivities: 记录运行在该ActivityStack中的Activity
    • mStacks: 保存一个ActivityDisplay中其他的ActivityStack,包含自身

    ActivityDisplay

    管理一个显示器上的0个或多个ActivityStack

    ActivityStackSupervisor

    管理所有显示设备上的ActivityStack

    ActivityStarter

    管理Activity如何运行,以及与Task、ActivityStack之间的关联

    小结

    Activity、Task以及ActivityStack之间的关系如图所示


    其中,Task以栈的方式管理ActivityRecord,ActivityStack不以栈的方式管理Task。了解了上述类之间的关系之后,我们来看Activity的启动模式

    standard(默认模式)

    系统在启动Activity的任务中创建Activit 的新实例并向其传送Intent。Activity可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。

    singleTop

    与standard的区别在于如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。其他与standard相同。

    singleTask

    系统中只能存在一个Activity的实例,但是,如果该 Activity 的一个实例已存在于一个任务中,则系统会通过调用现有实例的onNewIntent()方法向其传送Intent,而不是创建新实例。与singleInstance的区别在于Activity所在的Task可以有其他的Activity实例。

    singleInstance

    与singleTask类似,区别在于该 Activity 始终是其任务唯一成员。

    Activity的启动过程

    我们以Activity上下中调用startActivity为例分析。

    Source Activity请求System启动Target Activity的过程

    从startActivity开始分析,在startActivity中直接调用startActivityForResult,我们直接看这个函数。

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
    
            ......
    }
    

    在startActivityForResult中进一步调用execStartActivity,其中,参数this为启动Activity的上下文,
    mMainThread.getApplicationThread()返回ApplicationThread对象(Binder实体对象),主要用于与System进程通信;mToken为Binder代理对象(建立Activity与其窗口的连接)。接下来分析execStartActivity。

    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
            Uri referrer = target != null ? target.onProvideReferrer() : null;
            if (referrer != null) {
                intent.putExtra(Intent.EXTRA_REFERRER, referrer);
            }
            // ActivityMonitor用于监控特定的Intent以及查询Activity创建等,具体请参考source code.
            if (mActivityMonitors != null) {
                synchronized (mSync) {
                    final int N = mActivityMonitors.size();
                    for (int i=0; i<N; i++) {
                        final ActivityMonitor am = mActivityMonitors.get(i);
                        if (am.match(who, null, intent)) {
                            am.mHits++;
                            if (am.isBlocking()) {
                                return requestCode >= 0 ? am.getResult() : null;
                            }
                            break;
                        }
                    }
                }
            }
            try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                // 调用ActivityManagerService的Binder代理对象ActivityManagerProxy的
                // startActivity.
                int result = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
    
            ......
    
    }
    

    这里注意ActivityManagerNative.getDefault()返回的可以能Binder代理对象,也可能是Binder实体对象,取决于调用者所在的进程与服务提供者进程是否相同,相同则返回Binder实体对象,不同则返回Binder代理对象。下面分析System进程收到请求后启动Target Activity宿主进程的过程。

    System启动Target Activity宿主进程的过程

    ActivityManagerService继承自ActivityManagerNative,我们从ActivityManagerNative的onTransact开始分析。

        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
            switch (code) {
            // 收到startActivity请求
            case START_ACTIVITY_TRANSACTION:
            {
                data.enforceInterface(IActivityManager.descriptor);
                // 返回Binder代理对象
                IBinder b = data.readStrongBinder();
                // 创建ApplicationThreadProxy对象
                IApplicationThread app = ApplicationThreadNative.asInterface(b);
                String callingPackage = data.readString();
                Intent intent = Intent.CREATOR.createFromParcel(data);
                String resolvedType = data.readString();
                IBinder resultTo = data.readStrongBinder();
                String resultWho = data.readString();
                int requestCode = data.readInt();
                int startFlags = data.readInt();
                ProfilerInfo profilerInfo = data.readInt() != 0
                        ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
                Bundle options = data.readInt() != 0
                        ? Bundle.CREATOR.createFromParcel(data) : null;
                int result = startActivity(app, callingPackage, intent, resolvedType,
                        resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
                reply.writeNoException();
                reply.writeInt(result);
                return true;
            }
            ......
        }
    

    这里说明下,Binder对象的传输,分为以下几种情况(分析writeStrongBinder方法实现以及Binder驱动代码可知):

    • 发送Binder实体对象:接收方接收到Binder代理对象
    • 发送Binder代理对象:如果接收方进程与服务提供者进程形同,接收到Binder实体对象,否则接收到Binder代理对象。在startActivity中,ApplicationThread对象从应用端发送,System进程接收到ApplicationThreadProxy对象。startActivity直接调用startActivityAsUser,下面分析startActivityAsUser。
        public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
            enforceNotIsolatedCaller("startActivity");
            userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                    userId, false, ALLOW_FULL_ONLY, "startActivity", null);
            // TODO: Switch to user app stacks here.
            return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, bOptions, false, userId, null, null);
        }
    

    在startActivityAsUser中,调用ActivityStarter的startActivityMayWait方法。ActivityStarter用于管理Activity如何运行,以及与Task、ActivityStack之间的关联,我们重点关注它是如何管理Activity的LaunchMode。下面看startActivityMayWait。

        final int startActivityMayWait(IApplicationThread caller, int callingUid,
                String callingPackage, Intent intent, String resolvedType,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int startFlags,
                ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
                Bundle bOptions, boolean ignoreTargetSecurity, int userId,
                IActivityContainer iContainer, TaskRecord inTask) {
            // Refuse possible leaked file descriptors
            if (intent != null && intent.hasFileDescriptors()) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
            mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
            boolean componentSpecified = intent.getComponent() != null;
    
            // Save a copy in case ephemeral needs it
            final Intent ephemeralIntent = new Intent(intent);
            // Don't modify the client's object!
            intent = new Intent(intent);
    
            // 向PackageManagerService查询intent信息,返回ResolveInfo包含目标ActivityInfo、ApplicationInfo等
            ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
            ......
            // Collect information about the target of the Intent.
            // 从ResolveInfo中得到ActivityInfo
            ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
            ......
            synchronized (mService) {
                final ActivityRecord[] outRecord = new ActivityRecord[1];
                // 运行Target Activity
                int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                        aInfo, rInfo, voiceSession, voiceInteractor,
                        resultTo, resultWho, requestCode, callingPid,
                        callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                        options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                        inTask);
    
                ......
                if (outResult != null) {
                    outResult.result = res;
                    if (res == ActivityManager.START_SUCCESS) {
                        mSupervisor.mWaitingActivityLaunched.add(outResult);
                        do {
                            try {
                                // 等待Target Activity启动完成
                                mService.wait();
                            } catch (InterruptedException e) {
                            }
                        } while (outResult.result != START_TASK_TO_FRONT
                                && !outResult.timeout && outResult.who == null);
                        if (outResult.result == START_TASK_TO_FRONT) {
                            res = START_TASK_TO_FRONT;
                        }
                    }
                    ......
                }
                ......
            }
        }
    

    下面分析startActivityLocked。

        final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
                String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
                String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
                ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
                ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
                TaskRecord inTask) {
            int err = ActivityManager.START_SUCCESS;
    
            ProcessRecord callerApp = null;
            if (caller != null) {
                // 根据IApplicationThread对象得到SourceActivity 宿主进程的ProcessRecord
                callerApp = mService.getRecordForAppLocked(caller);
                if (callerApp != null) {
                    callingPid = callerApp.pid;
                    callingUid = callerApp.info.uid;
                } else {
                    Slog.w(TAG, "Unable to find app for caller " + caller
                            + " (pid=" + callingPid + ") when starting: "
                            + intent.toString());
                    err = ActivityManager.START_PERMISSION_DENIED;
                }
            }
            ......
            ActivityRecord sourceRecord = null;
            ActivityRecord resultRecord = null;
            if (resultTo != null) {
                // 以Source Activity的token为索引,如果Source Activity在某个ActviityStack中则返回ActivityRecord,否则返回null
                sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
                if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                        "Will send result to " + resultTo + " " + sourceRecord);
                if (sourceRecord != null) {
                    if (requestCode >= 0 && !sourceRecord.finishing) {
                        resultRecord = sourceRecord;
                    }
                }
            }
            ......
            // 检查是否允许启动Target Activity
            boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
                    resultRecord, resultStack, options);
            abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                    callingPid, resolvedType, aInfo.applicationInfo);
            ......
            // 为Target Activity创建ActivityRecord
            ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                    intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                    requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
                    options, sourceRecord);
            if (outActivity != null) {
                outActivity[0] = r;
            }
            ......
            // 运行Pending的ActivityRecord
            doPendingActivityLaunchesLocked(false);
    
            try {
                mService.mWindowManager.deferSurfaceLayout();
                // 运行Target Activity
                err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                        true, options, inTask);
            } finally {
                mService.mWindowManager.continueSurfaceLayout();
            }
            postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
            return err;
        }
    

    startActivityUnchecked是计算Target Activity LaunchMode的核心函数,下面进行分析。

        private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
    
            // 标记正在启动的Target Activity以及调整Target Actvity的LaunchMode等
            setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                    voiceInteractor);
    
            // 根据Source Activity计算Target Activity的LaunchMode
            // 1)非Activity上下文启动Target Activity
            // 2)Source Activity是singleInstance
            // 3)Target Activity的LaunchMode是singleInstance或者singleTask
            // 以上情况下,LaunchMode设置FLAG_ACTIVITY_NEW_TASK标志位
            computeLaunchingTaskFlags();
    
            // 获取Source Activity所在的ActivityStack
            // 如果Source Activity处于finishing,LaunchMode设置FLAG_ACTIVITY_NEW_TASK标志位
            computeSourceStack();
    
            mIntent.setFlags(mLaunchFlags);
    
            // 计算是否需要将Target Activity添加到存在的某个Task中,如果需要创建新的Task,`mReusedActivity = null`
            // 否则返回重用的Task中的ActivityRecord
            mReusedActivity = getReusableIntentActivity();
            ......
            // 只需将Target Activity添加到某个存在的Task中
            if (mReusedActivity != null) {
                // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
                // still needs to be a lock task mode violation since the task gets cleared out and
                // the device would otherwise leave the locked task.
                if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                    mSupervisor.showLockTaskToast();
                    Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                    return START_RETURN_LOCK_TASK_MODE_VIOLATION;
                }
    
                // 设置Target Activity所属的TaskRecord
                if (mStartActivity.task == null) {
                    mStartActivity.task = mReusedActivity.task;
                }
                if (mReusedActivity.task.intent == null) {
                    // This task was started because of movement of the activity based on affinity...
                    // Now that we are actually launching it, we can assign the base intent.
                    mReusedActivity.task.setIntent(mStartActivity);
                }
    
                // This code path leads to delivering a new intent, we want to make sure we schedule it
                // as the first operation, in case the activity will be resumed as a result of later
                // operations.
                if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                        || mLaunchSingleInstance || mLaunchSingleTask) {
                    // In this situation we want to remove all activities from the task up to the one
                    // being started. In most cases this means we are resetting the task to its initial
                    // state.
                    // FLAG_ACTIVITY_CLEAR_TOP || SingleInstance || SingleTask情况下,需要清理重用的Task中Target Activity
                    // 到栈顶的ActivityRecord。
                    final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
                            mStartActivity, mLaunchFlags);
                    ......
                }
            }
            ......
            // 打印事件log:am_create_activity
            ActivityStack.logStartActivity(
                    EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
            mTargetStack.mLastPausedActivity = null;
            mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
            ......
            if (mDoResume) {
                if (!mLaunchTaskBehind) {
                    // TODO(b/26381750): Remove this code after verification that all the decision
                    // points above moved targetStack to the front which will also set the focus
                    // activity.
                    mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
                }
                final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
                if (!mTargetStack.isFocusable()
                        || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                        && mStartActivity != topTaskActivity)) {
                    // If the activity is not focusable, we can't resume it, but still would like to
                    // make sure it becomes visible as it starts (this will also trigger entry
                    // animation). An example of this are PIP activities.
                    // Also, we don't want to resume activities in a task that currently has an overlay
                    // as the starting activity just needs to be in the visible paused state until the
                    // over is removed.
                    mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                    // Go ahead and tell window manager to execute app transition for this activity
                    // since the app transition will not be triggered through the resume channel.
                    mWindowManager.executeAppTransition();
                } else {
                    // 运行Focused ActivityStack的TopActivity也就是Target Activity
                    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                            mOptions);
                }
            } else {
                mTargetStack.addRecentActivityLocked(mStartActivity);
            }
            ......
    
        }
    

    startActivityUnchecked中关于LaunchMode的计算以及Task/ActivityStack的处理比较复杂,要根据具体的情况而定,对于细节请自行撸码。下面继续看ActivityStack的startActivityLocked方法。

        final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
                ActivityOptions options) {
            TaskRecord rTask = r.task;
            final int taskId = rTask.taskId;
            // mLaunchTaskBehind tasks get placed at the back of the task stack.
            if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
                // Last activity in task had been removed or ActivityManagerService is reusing task.
                // Insert or replace.
                // Might not even be in.
                insertTaskAtTop(rTask, r);
                mWindowManager.moveTaskToTop(taskId);
            }
            TaskRecord task = null;
            if (!newTask) {
                // If starting in an existing task, find where that is...
                ......
            }
            ......
    
            // 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();
    
            r.putInHistory();
            if (!isHomeStack() || numActivities() > 0) {
                // 显示starting window当切换Task或者正在启动的Target Activity宿主进程还没有运行时
                ......
                // 准备starting window的过渡动画
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                    mNoAnimActivities.add(r);
                } else {
                    mWindowManager.prepareAppTransition(newTask
                            ? r.mLaunchTaskBehind
                                    ? TRANSIT_TASK_OPEN_BEHIND
                                    : TRANSIT_TASK_OPEN
                            : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                    mNoAnimActivities.remove(r);
                }
                ......
                } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                ......
                    // 显示starting window
                     r.showStartingWindow(prev, showStartingIcon);
            }
        }
    
    

    回到startActivityUnchecked中,我们看resumeFocusedStackTopActivityLocked的过程

        boolean resumeFocusedStackTopActivityLocked(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
            if (targetStack != null && isFocusedStack(targetStack)) {
                // 检查targetStack后,调用resumeTopActivityUncheckedLocked
                return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            }
            final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
            if (r == null || r.state != RESUMED) {
                mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
            }
            return false;
        }
    

    在resumeTopActivityUncheckedLocked中,调用继续调用resumeTopActivityInnerLocked。

        private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
    
            // 系统尚未启动完成
            if (!mService.mBooting && !mService.mBooted) {
                // Not ready yet!
                return false;
            }
            ......
            // Find the first activity that is not finishing.
            final ActivityRecord next = topRunningActivityLocked();
            ......
            // pause当前处于resume的前台Activity
            // We need to start pausing the current activity so the top one can be resumed...
            final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
            boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
            if (mResumedActivity != null) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Pausing " + mResumedActivity);
                pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
            }
            ......
            if (next.app != null && next.app.thread != null) {
                // Target Activity宿主进程存在
                ......
                try {
                    ......
                    // 打印AM_RESUME_ACTIVITY事件Log
                    EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                            System.identityHashCode(next), next.task.taskId, next.shortComponentName);
                    ......
                    // 调度应用运行Target Activity
                    next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                            mService.isNextTransitionForward(), resumeAnimOptions);
    
                }
                ......
            } else {
                // Target Activity宿主进程不存在
                // Whoops, need to restart this activity!
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else {
                    if (SHOW_APP_STARTING_PREVIEW) {
                        next.showStartingWindow(null, true);
                    }
                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
                }
                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
                mStackSupervisor.startSpecificActivityLocked(next, true, true);
            }
    
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }
    

    我们关注Target Activity宿主进程不存在的情况,下面分析startSpecificActivityLocked。

        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) {
                // Target Activity的宿主进程已经运行
                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);
                    }
                    // 调度应用运行Activity
                    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.
            }
    
            // 为Tatget Activity创建宿主进程(通过socket请求Zygote fork进程)
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false, false, true);
        }
    
        private final void startProcessLocked(ProcessRecord app, String hostingType,
                String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            long startTime = SystemClock.elapsedRealtime();
            if (app.pid > 0 && app.pid != MY_PID) {
                checkTime(startTime, "startProcess: removing from pids map");
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.remove(app.pid);
                    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
                }
                checkTime(startTime, "startProcess: done removing from pids map");
                app.setPid(0);
            }
            ......
            try {
                boolean isActivityProcess = (entryPoint == null);
                // 应用进程的入口
                if (entryPoint == null) entryPoint = "android.app.ActivityThread";
                // systrace
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                        app.processName);
                checkTime(startTime, "startProcess: asking zygote to start proc");
                // 请求zygote fork进程
                Process.ProcessStartResult startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                        app.info.dataDir, entryPointArgs);
                checkTime(startTime, "startProcess: returned from zygote!");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                ......
                // 事件log AM_PROC_START
                EventLog.writeEvent(EventLogTags.AM_PROC_START,
                        UserHandle.getUserId(uid), startResult.pid, uid,
                        app.processName, hostingType,
                        hostingNameStr != null ? hostingNameStr : "");
                ......
                synchronized (mPidsSelfLocked) {
                    // 将zygote fork出的进程的pid添加到mPidsSelfLocked
                    this.mPidsSelfLocked.put(startResult.pid, app);
                    if (isActivityProcess) {
                        Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                        msg.obj = app;
                        // 设置应用进程attach的超时消息
                        mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                                ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
                    }
                }
            }
            ......
        }
    

    Tatget Activity宿主进程运行后,会进入ActivityThread的main方法,也就是attach的过程。

    Target Activity宿主进程attach的过程

        public static void main(String[] args) {
            // systrace中的ActivityThreadMain
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
            ......
    
            // UI线程 Looper
            Looper.prepareMainLooper();
    
            // 创建ActivityThread对象,这是一个GC Root对象
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            if (false) {
                Looper.myLooper().setMessageLogging(new
                        LogPrinter(Log.DEBUG, "ActivityThread"));
            }
    
            // End of event ActivityThreadMain.
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            // 进入loop循环处理消息
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    
    

    下面看ActivityThread的attach方法。

        private void attach(boolean system) {
            sCurrentActivityThread = this;
            mSystemThread = system;
            // 应用进程
            if (!system) {
                ViewRootImpl.addFirstDrawHandler(new Runnable() {
                    @Override
                    public void run() {
                        ensureJitEnabled();
                    }
                });
                android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                        UserHandle.myUserId());
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
    
                // 这里mgr是ActivityManagerProxy对象
                final IActivityManager mgr = ActivityManagerNative.getDefault();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
                ......
            }
            ......
        }
    

    在attach方法中调用ActivityManagerProxy对象的attachApplication,参数mAppThread是ApplicationThread对象。attachApplication是Binder RPC,最终调用ActivityManagerService的attachApplication方法。

        public final void attachApplication(IApplicationThread thread) {
            synchronized (this) {
                // Target Activity宿主进程pid
                // 参数thread 是ApplicationThreadProxy对象
                int callingPid = Binder.getCallingPid();
                final long origId = Binder.clearCallingIdentity();
                attachApplicationLocked(thread, callingPid);
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    继续看attachApplicationLocked的实现。

        private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid) {
    
            // Find the application record that is being attached...  either via
            // the pid if we are running in multiple processes, or just pull the
            // next app record if we are emulating process with anonymous threads.
            ProcessRecord app;
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    // 通过pid找到进程记录
                    app = mPidsSelfLocked.get(pid);
                }
            } else {
                app = null;
            }
            ......
            final String processName = app.processName;
            try {
                // 创建app死亡通知接收者,当应用进程死亡时,binder驱动告知客户端
                AppDeathRecipient adr = new AppDeathRecipient(
                        app, pid, thread);
                thread.asBinder().linkToDeath(adr, 0);
                app.deathRecipient = adr;
            } catch (RemoteException e) {
                app.resetPackageList(mProcessStats);
                startProcessLocked(app, "link fail", processName);
                return false;
            }
    
            // 事件log AM_PROC_BOUND
            EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
            ......
            // 移除应用进程attach超时消息
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
    
            boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
            List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
    
            if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
                // 如果正在执行attach的应用进程正在运行ContentProvider,设置超时消息
                Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
            }
            .....
            try {
                ......
                // 通过binder IPC请求应用进程bindApplication
                thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                        profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                        app.instrumentationUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(mConfiguration), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked());
            }
            // See if the top visible activity is waiting to run in this process...
            if (normalMode) {
                try {
                    // 运行top visible activity,也就是Target Activity
                    if (mStackSupervisor.attachApplicationLocked(app)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
            ......
        }
    

    bindApplication在下一节中讨论,先看attachApplicationLocked。

        boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
            final String processName = app.processName;
            boolean didSomething = false;
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    final ActivityStack stack = stacks.get(stackNdx);
                    if (!isFocusedStack(stack)) {
                        continue;
                    }
                    ActivityRecord hr = stack.topRunningActivityLocked();
                    if (hr != null) {
                        if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                                && processName.equals(hr.processName)) {
                            try {
                                // 启动Target Activity
                                if (realStartActivityLocked(hr, app, true, true)) {
                                    didSomething = true;
                                }
                            } catch (RemoteException e) {
                                Slog.w(TAG, "Exception in new application when starting activity "
                                      + hr.intent.getComponent().flattenToShortString(), e);
                                throw e;
                            }
                        }
                    }
                }
            }
            if (!didSomething) {
                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            }
            return didSomething;
        }
    

    下面分析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;
            }
            ......
            try {
                if (app.thread == null) {
                    throw new RemoteException();
                }
                List<ResultInfo> results = null;
                List<ReferrerIntent> newIntents = null;
                if (andResume) {
                    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);
                if (andResume) {
                    // 事件log AM_RESTART_ACTIVITY
                    EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
                            r.userId, System.identityHashCode(r),
                            task.taskId, r.shortComponentName);
                }
                ......
                // 调度应用运行Target Activity
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                        new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                        newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
            }
            ......
        }
    

    下面分析Target Activity宿主进程如何处理bindApplication和scheduleLaunchActivity。

    Target Activity宿主进程处理bindApplication以及运行Activity组件的过程

    我们首先分析bindApplication。

            public final void bindApplication(String processName, ApplicationInfo appInfo,
                    List<ProviderInfo> providers, ComponentName instrumentationName,
                    ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                    IInstrumentationWatcher instrumentationWatcher,
                    IUiAutomationConnection instrumentationUiConnection, int debugMode,
                    boolean enableBinderTracking, boolean trackAllocation,
                    boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                    CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
    
                if (services != null) {
                    // Setup the service cache in the ServiceManager
                    // 非ISOLATE进程(fully isolated sandboxed process)缓存用于访问PMS、WMS服务的BinderProxy对象
                    ServiceManager.initServiceCache(services);
                }
                ......
                // 向UI线程发送BIND_APPLICATION消息
                sendMessage(H.BIND_APPLICATION, data);
            }
    

    下面分析UI线程如何处理BIND_APPLICATION的消息。

        private void handleBindApplication(AppBindData data) {
            // Register the UI Thread as a sensitive thread to the runtime.
            VMRuntime.registerSensitiveThread();
            if (data.trackAllocation) {
                DdmVmInternal.enableRecentAllocations(true);
            }
    
            // Note when this process has started.
            Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
    
            mBoundApplication = data;
            mConfiguration = new Configuration(data.config);
            mCompatConfiguration = new Configuration(data.config);
    
            // 调式相关(TraceView/Method Profile),
            mProfiler = new Profiler();
            if (data.initProfilerInfo != null) {
                mProfiler.profileFile = data.initProfilerInfo.profileFile;
                mProfiler.profileFd = data.initProfilerInfo.profileFd;
                mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
                mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
            }
            ......
            if (data.persistent) {
                // Persistent processes在低内存设备上禁用硬件加速渲染,也就是RenderThread
                // Persistent processes on low-memory devices do not get to
                // use hardware accelerated drawing, since this can add too much
                // overhead to the process.
                if (!ActivityManager.isHighEndGfx()) {
                    ThreadedRenderer.disable(false);
                }
            }
            ......
            // 创建LoadedApk对象(负责管理Apk包的信息)
            data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
            ......
            // 创建appContext,注意并非我们常用的Application Context
            final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
            ......
            if (ii != null) {
                // 通常ii == null
                final ApplicationInfo instrApp = new ApplicationInfo();
                ii.copyTo(instrApp);
                instrApp.initForUser(UserHandle.myUserId());
                final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true, false);
                final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    
                try {
                    final ClassLoader cl = instrContext.getClassLoader();
                    mInstrumentation = (Instrumentation)
                        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(
                        "Unable to instantiate instrumentation "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
    
                final ComponentName component = new ComponentName(ii.packageName, ii.name);
                mInstrumentation.init(this, instrContext, appContext, component,
                        data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
    
                if (mProfiler.profileFile != null && !ii.handleProfiling
                        && mProfiler.profileFd == null) {
                    mProfiler.handlingProfiling = true;
                    final File file = new File(mProfiler.profileFile);
                    file.getParentFile().mkdirs();
                    Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
                }
            } else {
                // 创建Instrumentation对象,Instrumentation是应用与系统之间的桥梁
                mInstrumentation = new Instrumentation();
            }
            ......
            final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
            try {
                // If the app is being launched for full backup or restore, bring it up in
                // a restricted environment with the base application class.
                // 创建Application对象
                Application app = data.info.makeApplication(data.restrictedBackupMode, null);
                mInitialApplication = app;
    
                // don't bring up providers in restricted mode; they may depend on the
                // app's custom Application class
                if (!data.restrictedBackupMode) {
                    if (!ArrayUtils.isEmpty(data.providers)) {
                        //安装ContentProvider
                        installContentProviders(app, data.providers);
                        // For process that contains content providers, we want to
                        // ensure that the JIT is enabled "at some point".
                        mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                    }
                }
    
                // Do this after providers, since instrumentation tests generally start their
                // test thread at this point, and we don't want that racing.
                try {
                    mInstrumentation.onCreate(data.instrumentationArgs);
                }
                catch (Exception e) {
                    throw new RuntimeException(
                        "Exception thrown in onCreate() of "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
    
                try {
                    // 调用Application对象的onCreate方法
                    mInstrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!mInstrumentation.onException(app, e)) {
                        throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                            + ": " + e.toString(), e);
                    }
                }
            } finally {
                StrictMode.setThreadPolicy(savedPolicy);
            }
        }
    

    在handleBindApplication过程中,makeApplication相对复杂,下面分析makeApplication的实现。

        public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
            if (mApplication != null) {
                return mApplication;
            }
    
            // systrace中的makeApplication
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
    
            Application app = null;
    
            String appClass = mApplicationInfo.className;
            if (forceDefaultAppClass || (appClass == null)) {
                appClass = "android.app.Application";
            }
    
            try {
                // 创建应用的类加载器
                java.lang.ClassLoader cl = getClassLoader();
                if (!mPackageName.equals("android")) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            "initializeJavaContextClassLoader");
                    initializeJavaContextClassLoader();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
                // 创建Application上下文实现对象
                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
                // 创建Application,调用其attach方法
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
                // 设置outerContext
                appContext.setOuterContext(app);
            } catch (Exception e) {
            ......
            }
            ......
        }
    

    下面分析UI线程处理scheduleLaunchActivity,我们直接看handleLaunchActivity.

        private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
            mSomeActivitiesChanged = true;
    
            if (r.profilerInfo != null) {
                mProfiler.setProfiler(r.profilerInfo);
                mProfiler.startProfiling();
            }
    
            // Make sure we are running with the most recent config.
            handleConfigurationChanged(null, null);
    
            if (localLOGV) Slog.v(
                TAG, "Handling launch of " + r);
    
            // Initialize before creating the activity
            // 初始化窗口管理,主要是获取WMS服务的代理对象
            WindowManagerGlobal.initialize();
    
            // 创建Activity及其上下文实现对象,执行onCreate()及onStart()方法
            Activity a = performLaunchActivity(r, customIntent);
            if (a != null) {
                r.createdConfig = new Configuration(mConfiguration);
                reportSizeConfigurations(r);
                Bundle oldState = r.state;
                // 执行Activity的onResume()方法
                handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
                ......
            }
        }
    

    小结

    相关文章

      网友评论

          本文标题:从LaunchMode看Android Activity的启动

          本文链接:https://www.haomeiwen.com/subject/sdpevxtx.html