Android四大组件系列2 Activity启动流程(上)

一 概述

Activity 的启动分为不同进程间和相同进程内部的启动。由于进程间 Activity 启动流程包括了相同进程内部 Activity 启动的流程。因此本文只分析不同进程间,比如点击 Launcher 桌面图标启动 Activity 的整个过程。在阅读本篇文章之前,建议同学们先了解下 AMS 相关的数据结构和管理机制,可参考 Android四大组件系列1 AMS相关数据结构。

时序图如下:
Android四大组件系列2 Activity启动流程(上)_第1张图片
涉及代码如下:

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
frameworks/base/services/core/java/com/android/server/wm/ActivityDisplay.java
frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
 
frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/app/Instrumentation.java
frameworks/base/core/java/android/app/ActivityTaskManager.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/AppComponentFactory.java
frameworks/base/core/java/android/app/FragmentController.java
 
frameworks/base/core/java/android/app/ClientTransactionHandler.java
frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
frameworks/base/core/java/android/app/servertransaction/TransactionExecutorHelper.java
frameworks/base/core/java/android/app/servertransaction/ActivityLifecycleItem.java
frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

二 startActivity阶段

我们知道,我们可以在自己的应用中的 Activity 中通过 startActivity 就可以发送一个 Intent 然后启动一个新的应用,这里边调用的就是 Activity.startActivity,我们来看这个函数,需要注意的是这些个操作都是在发起端进程中执行的。这个发起端可以是 Launcher,也可以是任何调用 startActivity 的应用。

2.1 Activity.startActivity

frameworks/base/core/java/android/app/Activity.java

public void startActivity(Intent intent) {
        this.startActivity(intent, null);
}

public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {           
            startActivityForResult(intent, -1);
        }
}

2.2 Activity.startActivityForResult

public void startActivityForResult(@RequiresPermission Intent intent,
        int requestCode) { // 从当前应用进程跨进程跳转到了 AMS
        startActivityForResult(intent, requestCode, null);
}

public void startActivityForResult(@RequiresPermission Intent intent,
     int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            // 调用 Instrumentation 的 execStartActivity 方法,继续执行
            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());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }
            ......
        } else {
            ......
        }
    }

2.3 Instrumentation.execStartActivity

frameworks/base/core/java/android/app/Instrumentation.java

public ActivityResult execStartActivity(
    Context who, IBinder contextThread, ......) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
        ......
        try {
            ......
            // 跨进程调用 ActivityTaskManagerService.startActivity
            int result = ActivityTaskManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
            // 检查 result, 判断 Activity 是否启动成功.
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
  • who:启动 Activity 的上下文
  • contextThread:ActivityThread 中的 ApplicationThread 对象 mAppThread
  • token:令牌,标识着 Activity,系统唯一标识
  • target:在哪个 Activity 中启动,会接收启动完成的结果
  • intent:启动意图
  • requestCode:请求码,用于将结果和请求对应上
  • options:可选参数

execStartActivity 里面我们需要重点关注两个参数。

mMainThread.getApplicationThread() 会返回一个 ApplicationThread 类型的变量。这个变量我们在 Android四大组件系列1 AMS相关数据结构 中已经介绍过,这里 ApplicationThread 代表的是发起请求的客户端进程,后面 AMS 就是通过它来和客户端进程进行跨进程通信的。

第二个需要重点关注的就是 mToken,mToken 我们在之前也介绍过了,它是连接 ActivityRecord,Activity,ActivityClientRecord 的桥梁,AMS 通过它就可以获取客户端进程中的 Activity 的详细信息。

最后通过 Binder 调用 ActivityTaskManagerService 的 startActivity 函数,之前讲过 ATMS 是用来分担 AMS 的一些功能的。从这个地方开始就从当前应用进程跨进程跳转到了 AMS,接下来我们来看 AMS 是怎么处理响应的。

2.4 ActivityTaskManagerService.startActivity

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

public final int startActivity(IApplicationThread caller,
    String callingPackage, Intent intent, String resolvedType,
    IBinder resultTo, String resultWho, int requestCode, int startFlags,
    ProfilerInfo profilerInfo, Bundle bOptions) {
        // 指定启动 Activity 的 userId
        return startActivityAsUser(caller, callingPackage, intent,
            resolvedType, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, bOptions, UserHandle.getCallingUserId());
}
    
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        // 继续调用 startActivityAsUser
        return startActivityAsUser(caller, callingPackage, intent,
            resolvedType, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, bOptions, userId, true /*validateIncomingUser*/);
}

int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, 
            ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        // 确保调用进程不是 isolated
        enforceNotIsolatedCaller("startActivityAsUser");
        // 检查 userId 的有效性, 并返回有效的 userId
        userId = getActivityStartController().checkTargetUser(userId,
            validateIncomingUser, Binder.getCallingPid(),
            Binder.getCallingUid(), "startActivityAsUser");
        // ActivityStartController#obtainStarter(),拿到 ActivityStarter
        // ActivityStarter#execute(),启动 Activity
        return getActivityStartController().obtainStarter(intent,
           "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
}

在 ATMS 的 startActivityAsUser 方法中会获取并初始化 ActivityStater 对象,然后调用它的 execute 方法,用来启动 Activity。注意倒数第二个 setMayWait() 方法,会将 mRequest.mayWait 属性设为 true。

ActivityStarter.java

ActivityStarter setMayWait(int userId) {
        mRequest.mayWait = true;
        mRequest.userId = userId;
        return this;
    }

2.5 ActivityStarter.execute

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

int execute() {
        try {
            if (mRequest.mayWait) {// 需要等待请求返回结果
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                       mRequest.callingPackage, mRequest.realCallingPid,
                       ......);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, 
                     mRequest.ephemeralIntent,  mRequest.resolvedType,
                     ......);
            }
        } finally {
            onExecutionComplete();// 执行完成
        }
    }

由上面的分析可知,这里的 mRequest.mayWait 为 true,是在上一步创建 ActivityStarter 实例时,通过调用 setMayWait 设置的。

2.6 ActivityStarter.startActivityMayWait

private int startActivityMayWait(IApplicationThread caller, int callingUid,
            ......) {
        ......
        // PakageManagerService 解析 intent(要启动的 APP 的 intent),
        // 获取 Activity 更多的信息
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType,
            userId, 0 /* matchFlags */,
            computeResolveFilterUid(
            callingUid, realCallingUid, mRequest.filterCallingUid));
        ......
        // Collect information about the target of the Intent.
        ActivityInfo aInfo = mSupervisor.resolveActivity(
                intent, rInfo, startFlags, profilerInfo);
        synchronized (mService.mGlobalLock) {
            ......
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            // 调用 startActivity
            int res = startActivity(caller, intent, ephemeralIntent,
                ......);
            ......
            return res;
        }
}

2.7 ActivityStarter.startActivity

private int startActivity(IApplicationThread caller, Intent intent,
            ......) {
        ......
        // 继续调用 startActivity
        mLastStartActivityResult = startActivity(caller, intent,
            ......);
        ......
        return getExternalResult(mLastStartActivityResult);
}


private int startActivity(IApplicationThread caller, Intent intent,
        ......) {
        ......
    int err = ActivityManager.START_SUCCESS;
    // 下面这段代码是确定源 Activity 和目的 Activity
    // 通常 sourceRecord 和 resultRecord 是同一个    
    ActivityRecord sourceRecord = null; // 源 Activity, 启动 Activity 的那个 Activity
    // 需要接收 result 的目的 Activity, 将启动结果返回给它 
    ActivityRecord resultRecord = null; 
    // 根据启动 Activity 的 token, 判断 Activity Stack 中是否有对应的源 Activity
    // 如果 requestCode>=0 且源 Activity 非空且非 finish, 则目的 Activity 即为源 Activity
    if (resultTo != null) {
        sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
        if (sourceRecord != null) {
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }
    // launchFlags 就是 Activity 的启动参数
    final int launchFlags = intent.getFlags();
    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 &&
        sourceRecord != null) {
      // 如果启动参数包含 FLAG_ACTIVITY_FORWARD_RESULT,则需要对 resultRecord 进行调整
    }

    // 以下代码都是进行一些常规检查,如果不符合条件,则给定一个错误码,标记启动失败
    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

    if (err == ActivityManager.START_SUCCESS && aInfo == null) {
         err = ActivityManager.START_CLASS_NOT_FOUND;
    }
    ......
    final ActivityStack resultStack = resultRecord == null
                ? null : resultRecord.getActivityStack();

// 如果错误码被标记上,表示上面的常规检查没有通过,需要结束 Activity 的启动过程 
    if (err != START_SUCCESS) {
        if (resultRecord != null) {
        // 此处,如果 resultRecord 不为 null,则需要告诉调用者启动失败了
             resultStack.sendActivityResultLocked(
                  -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
        }
        SafeActivityOptions.abort(options);
        return err;
    }

    // 常规检查通过,又要开始进行一系列的权限检查。上面是通过错误码 err 来标记
    // 权限检查是通过 abort 这个变量来标记的
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, ......);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
           callingPid, resolvedType, aInfo.applicationInfo);
    ......
    // 拦截器处理
    if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask,
            callingPid, callingUid, checkedOptions)) {
        ......
    } 
    ......
    if (abort) {
         if (resultRecord != null) {
             resultStack.sendActivityResultLocked(-1, resultRecord, ......);
         }
         ActivityOptions.abort(checkedOptions);
         // 如果权限检查失败,会中断 Activity 的启动过程,返回 START_ABORTED
         return START_ABORTED;
     }
    ......
    mService.onStartActivitySetDidAppSwitch();
    mController.doPendingActivityLaunches(false);
	// 最关键点:创建 ActivityRecord
    ActivityRecord r = new ActivityRecord(mService, callerApp,
	        ......);
    // 继续 startActivity
    final int res = startActivity(r, sourceRecord, voiceSession,
		    ......); 
    return res;
}


private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                ......) {
        int result = START_CANCELED;
        final ActivityStack startedActivityStack;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession,
                    ......);
        } finally {
            ......
        }
        postStartActivityProcessing(r, result, startedActivityStack);
        return result;
}

这个函数非常重要,关键节点在于创建了一个 ActivityRecord:

  • 在创建之前要进行参数设置 (sourceRecord 和 resultRecord 等)、常规检查 (譬如调用者的包名是否存在)、权限检查
  • 在创建 ActivityRecord 之后,也有一些处理,包括 AppSwitch,优先启动之前被阻塞的 Activity,然后,进入了 Activity 过程的下一阶段:startActivityUncheckedLocked(),从函数命名可以看出,该做的检查已经做完了,剩下的函数调用就不需要进行额外的检查了 (Unchecked)。

2.8 ActivityStarter.startActivityUnchecked

private int startActivityUnchecked(final ActivityRecord r,
            ......) {
   ......
   // 计算 mLaunchFlags
   computeLaunchingTaskFlags();
   // 设置刚才在上面计算出来的 mLaunchFlags
   mIntent.setFlags(mLaunchFlags);
   // 根据 mLaunchFlags 来查找是否有可重用的 activity
   ActivityRecord reusedActivity = getReusableIntentActivity();
   if (reusedActivity != null) {
     // 如果找到了可重用的 activity,需要清理掉原来的信息,并把当前启动的 
     // activity 的信息拷贝进去,做清理和拷贝工作
     ......
     if((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 ||
           isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)){
       // 没必要新建实例,回调 onNewIntent 并将 top 移至前台
       deliverNewIntent(top);
     }
     ......
   }
   ......
    // Should this be considered a new task?
    // 将要启动的 Activity(即 mStartActivity)添加到 task 里, 同时将该
    // task 移到 task 列表的最前面,这个 task 可能是新建的 task
    // 也可能是启动 Activity 的当前 Activity 所在的 task
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;// 复用 task 或创建新的 task
        // TaskRecord,ActivityStack 就是在这个函数建立联系的
        result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
    } else if (mSourceRecord != null) {// 不是新建 task 的,重用原 activity 的 task
        result = setTaskFromSourceRecord();// 从 mSourceRecord 中获取 task
    } else if (mInTask != null) {
        result = setTaskFromInTask();// 从 mInTask 中获取 task
    } else {
        // 从 mHistoryTasks 栈顶获取 task 或创建新的 task
        result = setTaskToCurrentTopOrCreateNewTask();
    }
    ......
    // 启动 Activity 的准备工作
    mTargetStack.startActivityLocked(mStartActivity, topFocused,
            ......);
    if (mDoResume) {// resume 操作, 此处为 true
        // 获取当前正在运行的位于栈顶的 Activity
        final ActivityRecord topTaskActivity =
                mStartActivity.getTaskRecord().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
               || (topTaskActivity != null && topTaskActivity.mTaskOverlay
               && mStartActivity != topTaskActivity)) {
          // 设置启动的 Activity(即 mStartActivity)可见, 并通知 WindowManager 更新
            mTargetStack.ensureActivitiesVisibleLocked(mStartActivity,
               0, !PRESERVE_WINDOWS);
         mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
        } else {
    // 若 mTargetStack 栈当前没有显示在最上层并获取焦点, 则先将 mTargetStack 移到栈顶
         if (mTargetStack.isFocusable()
         && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
         }
            // 关键点 resume mStartActivity
            mRootActivityContainer.resumeFocusedStacksTopActivities(
                    mTargetStack, mStartActivity, mOptions);
        }
    } else if (mStartActivity != null) {
        // 将启动的 Activity 所在的 task 添加到最近任务列表 mRecentTasks 里
        mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
    }
    ......
    return START_SUCCESS;
}

startActivityUnchecked 是分配 Task 的重点函数,就是根据 activty 的启动模式找到合适的 task 来放置 activity,如果找不到,就会新建一个。具体过程如下:

  • 首先,根据 launchMode 和 Intent 中的 FLAG_ACTIVITY_NEW_TASK 等 flag 综合计算 activity 的启动模式,结果保存在 mLaunchFlags 中。计算的过程不仅要考虑目标 activity 的 launchMode,也要考虑原来 activity 的 launchMode 和 Intent 中所带着的 flag。例如原来 activity 的 launchMode 是LAUNCH_SINGLE_INSTANCE,那么新 activity 只能新建 task
  • 调用 getReusableIntentActivity() 查找是否有可以重用的 activity,这个只对 LAUNCH_SINGLE_INSTANCE 和 LAUNCH_SINGLE_TASK 或者 FLAG_ACTIVITY_NEW_ TASK 不为 0 有用的 actvity,对于 standard 的 activity,该方法永远返回 null。查找的依据包括 ActivityType、ComponentName 和 taskAffinity 等
  • 如果成功找到了可以重用的 activity,要进行清理工作,把原来 activity 的信息替换成现在 activity 的信息。例如同一个 activity,两次启动的 caller 可能不同,要进行更新。同时,还要进行根据 launchMode 来进行 task 内的清理。例如 LAUNCH_SINGLE_TASK 的 activity,如果此类所在的 task 上面有其它 Activity,那么其它的 Activity 会被销毁。
  • 找到了可以重用的 activity,那么就相当于把原来的 activty 替换成现在的 activty,也就不用新建 task 了。但是如果没有找到重用的 activity,那么调用 setTaskFromReuseOrCreateNewTask() 尝试寻找可以重用的 task,注意此时前提是 mStartActivity.resultTo == null && mLaunchFlags & FLAG_ACTIVITY_NEW_TASK,即,如果我们调用startActivityForResult 启动 activity,那么是不能新建 task 的,二者是不兼容的。没有找到重用的 task,此时会新建一个 TaskRecord,置于前台,然后把 activity 也置于 task 中 activity 队列的最后(即前台)。如果是重用原 activity 的 task,那么执行 setTaskFromSourceRecord,首先也是把该 task 移到前台,然后把 activity 置于该 task 的 activity 队列的最后
  • 经过前面四步,actvity 及其对应的 task 位置已经安排妥当,现在可以准备让这个 activity 开始工作了!那么这开工的第一步就是 mTargetStack.startActivityLocked,这里面的工作主要是通知 WMS 准备 activty 的过渡动画和 startingWindow

2.8.1 ActivityStarter.setTaskFromReuseOrCreateNewTask

private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        if (mRestrictedBgActivity && (mReuseTask == null || 
                !mReuseTask.containsAppUid(mCallingUid))
                && handleBackgroundActivityAbort(mStartActivity)) {
            return START_ABORTED;
        }
        // 获取目标 ActivityStack
        mTargetStack = computeStackFocus(mStartActivity, true,
            mLaunchFlags, mOptions);

        // Do no move the target stack to front yet, as we might bail if
        // isLockTaskModeViolation fails below.

    if (mReuseTask == null) {
        final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
     // 创建目标 TaskRecord
        final TaskRecord task = mTargetStack.createTaskRecord(
            mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
            mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
            mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
            mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
        // 把要启动的 ActivityRecord 添加到目标 TaskRecord 中
        addOrReparentStartingActivity(task,
            "setTaskFromReuseOrCreateNewTask - mReuseTask");
        updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);

    } else {
       addOrReparentStartingActivity(mReuseTask,
            "setTaskFromReuseOrCreateNewTask");
    }

        if (taskToAffiliate != null) {
            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
        }

        if (mService.getLockTaskController().isLockTaskModeViolation(
                mStartActivity.getTaskRecord())) {
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        if (mDoResume) {
            mTargetStack.moveToFront("reuseOrNewTask");
        }
        return START_SUCCESS;
}


private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
        if (mStartActivity.getTaskRecord() == null ||
            mStartActivity.getTaskRecord() == parent) {
            parent.addActivityToTop(mStartActivity);
        } else {
            mStartActivity.reparent(parent, parent.mActivities.size(), reason);
        }
}

为 activity 分配了任务栈之后,接下来调用 resumeFocusedStackTopActivityLocked。

2.9 RootActivityContainer.resumeFocusedStacksTopActivities()

boolean resumeFocusedStacksTopActivities(ActivityStack targetStack, 
        ActivityRecord target, ActivityOptions targetOptions) {
        if (!mStackSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
        if (targetStack != null && (targetStack.isTopStackOnDisplay()
                || getTopDisplayFocusedStack() == targetStack)) {
            result = targetStack.resumeTopActivityUncheckedLocked(
                target, targetOptions);
        }
        ......
        return result;
    }

2.10 ActivityStack.resumeTopActivityUncheckedLocked()

ActivityStack.java

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev,
     ActivityOptions options) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
            final ActivityRecord next = topRunningActivityLocked(true);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return result;
    }

2.11 ActivityStack.resumeTopActivityInnerLocked()

private boolean resumeTopActivityInnerLocked(ActivityRecord prev,
    ActivityOptions options) {
        if (!mService.isBooting() && !mService.isBooted()) {
            // Not ready yet!
            return false;
        }
        // next 是要 resume 的 activity
        ActivityRecord next = topRunningActivityLocked(true);
        ......
        // 关键函数
        boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
        ......
        // Launching this app's activity, make sure the app is no longer
        // considered stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                    next.packageName, false, next.mUserId);
        } catch (RemoteException e1) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                    + next.packageName + ": " + e);
        }
        ......
        return true;
}

这个方法会执行 getDisplay().pauseBackStacks() 这步,用于暂停当前的 Activity。getDisplay() 会返回 ActivityDisplay 对象。

ActivityDisplay.java

boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming,
    boolean dontWait) {
        boolean someActivityPaused = false;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityRecord resumedActivity = stack.getResumedActivity();
            if (resumedActivity != null
                    && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
                        || !stack.isFocusable())) {
                someActivityPaused |= 
                stack.startPausingLocked(userLeaving, false, resuming,
                        dontWait);
            }
        }
        return someActivityPaused;
    }

如果有符合条件的 Activity,则调用 stack.startPausingLocked 进入 pause 阶段。

三 pause阶段

在启动一个 Activity 的时候,如果发现当前还有处于 resume 状态的 Activity,会先走 puase 流程,暂停当前的 Activity。接上个阶段的分析我们知道,最终调用到了 ActivityDisplay 的 pauseBackStacks 方法。

ActivityDisplay.java

boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming,
    boolean dontWait) {
        boolean someActivityPaused = false;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityRecord resumedActivity = stack.getResumedActivity();
            if (resumedActivity != null
                    && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
                        || !stack.isFocusable())) {
                someActivityPaused |= 
                stack.startPausingLocked(userLeaving, false, resuming,
                        dontWait);
            }
        }
        return someActivityPaused;
    }

可以看到 pauseBackStacks 会执行以下操作:

  • pause 其他所有处于非 focus 状态的任务栈的 resumedActivity
  • pause 当前任务栈 resumedActivity

3.1 ActivityStack.startPausingLocked

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
        // 如果还有正在 pause 的 activity 那么等待执行结束
        if (mPausingActivity != null) {
            if (!shouldSleepActivities()) {
                completePauseLocked(false, resuming);
            }
        }
        ActivityRecord prev = mResumedActivity;
        ......
        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
        else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        mLastNoHistoryActivity = (prev.intent.getFlags() &
            Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ?
                 prev : null;
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTaskRecord().touchActiveTime();
        clearLaunchTime(prev);

        mService.updateCpuStats();

    if (prev.attachedToProcess()) {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
        try {
        // 关键调用 执行 PauseActivityItem
            mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
              prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
              prev.configChangeFlags, pauseImmediately));
        } catch (Exception e) {
            // Ignore exception, if process died other code will cleanup.
            Slog.w(TAG, "Exception thrown during pause", e);
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
    } else {
        mPausingActivity = null;
        mLastPausedActivity = null;
        mLastNoHistoryActivity = null;
    }
    ......
}

上面代码很简单,就是变更一下 mPausingActivity 的状态,然后通过 LifecycleManager 来通知 APP 进行 pause 操作,至此完成了所有 resumedActivity 的 pause 工作。关于 ClientLifecycleManager 机制,请参考 深入理解 ClientLifecycleManager 机制。

我们直接来看 PauseActivityItem 的 execute()方法。

3.2 PauseActivityItem.execute

@Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        client.handlePauseActivity(token, mFinished, 
        mUserLeaving, mConfigChanges, pendingActions,
                "PAUSE_ACTIVITY_ITEM");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

调用了 client 的 handlePauseActivity() 方法。我们知道 ActivityThread 继承了 ClientTransactionHandler ,并且也重写了这个方法,所以这里其实执行的是 ActivityThread 的 handlePauseActivity() 方法。

3.3 ActivityThread.handlePauseActivity

ActivityThread.java

public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
        int configChanges, PendingTransactionActions pendingActions, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        if (userLeaving) {
            performUserLeavingActivity(r);
        }

        r.activity.mConfigChangeFlags |= configChanges;
        performPauseActivity(r, finished, reason, pendingActions);
       ......
    }
}

3.4 ActivityThread.performPauseActivity

private Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
    String reason, PendingTransactionActions pendingActions) {
        if (r.paused) {
            if (r.activity.mFinished) {
        // If we are finishing, we won't call onResume() in certain cases.
       // So here we likewise don't want to call onPause() if the activity
       // isn't resumed.
                return null;
            }
            RuntimeException e = new RuntimeException(
                    "Performing pause of activity that is not resumed: "
                    + r.intent.getComponent().toShortString());
            Slog.e(TAG, e.getMessage(), e);
        }
        if (finished) {
            r.activity.mFinished = true;
        }

        // Pre-Honeycomb apps always save their state before pausing
        final boolean shouldSaveState = !r.activity.mFinished &&
            r.isPreHoneycomb();
        if (shouldSaveState) {
            callActivityOnSaveInstanceState(r);
        }
        // 关键调用
        performPauseActivityIfNeeded(r, reason);
        ......
        return shouldSaveState ? r.state : null;
    }

3.5 ActivityThread.performPauseActivityIfNeeded

ActivityThread.java

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
    ......
    try {
        r.activity.mCalled = false;
        mInstrumentation.callActivityOnPause(r.activity);
        ......
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        ......
    }
    r.setState(ON_PAUSE);
}

3.6 Instrumentation.callActivityOnPause

Instrumentation.java

public void callActivityOnPause(Activity activity) {
    activity.performPause();
}

3.7 Activity.performPause

Activity.java

final void performPause() {
	......
	onPause();// 回调 onPause 函数
	......
	dispatchActivityPostPaused();
}

最后在这里调用了我们当前 Activity 的 onPause 方法。也就是执行了 Activity 生命周期的 onPause 方法。

3.8 PauseActivityItem.postExecute

回到前面 TransactionExecutor 的 executeLifecycleState() 方法。在 PauseActivityItem 的 execute() 方法中执行了前一个 Activity 的 onPause() 方法,紧跟着会调用 PauseActivityItem 的 postExecute() 方法。ClientLifecycleManager 机制请参考 深入理解 ClientLifecycleManager 机制。

PauseActivityItem.java

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

调用 ActivityTaskManager.getService() 的 activityPaused 方法。也就是通过 Binder 机制跨进程调用系统进程中对应的 ActivityTaskManagerService 的 activityPaused 方法。

3.9 ActivityTaskManagerService.activityPaused

ActivityTaskManagerService.java

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

调用了 Activity 所在的 ActivityStack 的 activityPausedLocked 方法。

3.10 ActivityStack.activityPausedLocked

frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

final void activityPausedLocked(IBinder token, boolean timeout) {
	......
	if (r != null) {
		mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
		if (mPausingActivity == r) {
			......
			try {
				completePauseLocked(true, null);
			} finally {
				mService.mWindowManager.continueSurfaceLayout();
			}
			return;
		} else {
			......
		}
	}
	mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}

调用 completePauseLocked() 方法。

3.11 ActivityStack.completePauseLocked

frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
	ActivityRecord prev = mPausingActivity;
	......
	if (resumeNext) {
		final ActivityStack topStack =
		   mRootActivityContainer.getTopDisplayFocusedStack();
		if (!topStack.shouldSleepOrShutDownActivities()) {
			mRootActivityContainer.resumeFocusedStacksTopActivities(
			   topStack, prev, null);
		} else {
			......
		}
	}
	......
}

调用 RootActivityContainer 类的 resumeFocusedStacksTopActivities() 方法。发现这个方法在前面是看过的。

3.12 RootActivityContainer.resumeFocusedStacksTopActivities

RootActivityContainer.java

boolean resumeFocusedStacksTopActivities(ActivityStack targetStack, 
    ActivityRecord target, ActivityOptions targetOptions) {
	if (!mStackSupervisor.readyToResume()) {
		return false;
	}

	boolean result = false;
	if (targetStack != null && (targetStack.isTopStackOnDisplay()
			|| getTopDisplayFocusedStack() == targetStack)) {
		result = targetStack.resumeTopActivityUncheckedLocked(
		    target, targetOptions);
	}
	......
	return result;
}

调用 ActivityStack 的 resumeTopActivityUncheckedLocked() 方法。

3.13 ActivityStack.resumeTopActivityUncheckedLocked

frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev,
        ActivityOptions options) {
    if (mInResumeTopActivity) {
        return false;
    }
    boolean result = false;
    try {
        // Protect against recursion.
        mInResumeTopActivity = true;  
        result = resumeTopActivityInnerLocked(prev, options);     
        final ActivityRecord next = topRunningActivityLocked(true);
        if (next == null || !next.canTurnScreenOn()) {
            checkReadyForSleep();
        }
    } finally {
        mInResumeTopActivity = false;
    } 
    return result;
}

调用 resumeTopActivityInnerLocked() 方法。前面就是在这个方法中开始了 Activity 的 pause 流程,但是现在会开始新 Activity 的创建流程。

3.14 ActivityStack.resumeTopActivityInnerLocked

private boolean resumeTopActivityInnerLocked(ActivityRecord prev,
        ActivityOptions options) {
    ......
    // 从任务历史列表 mTaskHistory 里, 获取最上面运行的 Activity
    ActivityRecord next = topRunningActivityLocked(true);
    final boolean hasRunningActivity = next != null;
    if (!hasRunningActivity) {
        // 如果没有运行的 Activity, 则从其他 task 堆栈中查找 Activity 并 resume
        return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
    }
    // 如果 topRunningActivity 已经是 resume 状态, 则 do nothing
    if (mResumedActivity == next && next.isState(RESUMED) &&
            display.allResumedActivitiesComplete()) {
        executeAppTransition(options);
        return false;
    }
    ......
    // 如果没有获取到 topRunningActivity,则先暂停所有 Stack 中的 Activity.
    // 前面就是在这个方法中判断需要先 pause 当前 Activity 的
    boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
    // 暂停当前恢复态的 Activity(mResumedActivity),注意 prev/next 为要启动的
    // 目的 Activity, 而 mResumedActivity 为当前 Activity, 两者不是同一个
    if (mResumedActivity != null) {
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
    if (pausing && !resumeWhilePausing) {
        // 如果 Activity 正在 Pausing 状态,且不允许 pausing 过程中执行 resume, 则先不执行
        // resume 只是将即将启动的 Activity 所在的进程添加到 mLruProcesses 最前面, 避免被杀
        if (next.attachedToProcess()) {
            next.app.updateProcessInfo(false, true, false);
        }
        if (lastResumed != null) {
            lastResumed.setWillCloseOrEnterPip(true);
        }
        return true;
    } else if (mResumedActivity == next && next.isState(RESUMED) &&
                display.allResumedActivitiesComplete()) {
        // 如果要启动的 Activity 已经 Resume 了则不需要做什么
        // 调一下 executeAppTransition 执行一下 pending transitions 即可.
        executeAppTransition(options);
        return true;
    }
    ......
    // 如果下一个 Activity 已经可见了, 上一个 Activity 当前正处于 finishing 状态
    // 则直接让上一个 Activity 不可见,当上一个 Activity 不是 finishing 状态
    //(比如当下一个 Activity 不是全屏状态时的场景), 上一个 Activity 还应该是可见的
    if (prev != null && prev != next && next.nowVisible) {
        if (prev.finishing) {
            prev.setVisibility(false);
        }
    }
    ......
    if (next.attachedToProcess()) {// 不会走次分支,因为进程还没有启动起来
        // Activity 所在进程已启动, 和 realStartActivityLocked 做的事情类似.
        // 上一个 Activity 是否半透明
        final boolean lastActivityTranslucent = lastFocusedStack != null
                && (lastFocusedStack.inMultiWindowMode()
                || (lastFocusedStack.mLastPausedActivity != null
                && !lastFocusedStack.mLastPausedActivity.fullscreen)); 
        // 如果将要启动的Activity不可见, 则让该Activity可见
        if (!next.visible || next.stopped || lastActivityTranslucent) {
            next.setVisibility(true);
        }
        ......
        // 设置Activity状态为RESUMED
        next.setState(RESUMED, "resumeTopActivityInnerLocked");
        // 更新进程信息
        next.app.updateProcessInfo(false, true, true);
        ......
        final ClientTransaction transaction = 
                ClientTransaction.obtain(next.app.getThread(), next.appToken);
        // 分发所有pending结果
        ArrayList<ResultInfo> a = next.results;
        if (a != null) {
            final int N = a.size();
            if (!next.finishing && N > 0) {
                transaction.addCallback(ActivityResultItem.obtain(a));
            }
        } 
        // 分发new intent
        if (next.newIntents != null) {
            transaction.addCallback(NewIntentItem.obtain(next.newIntents, true));
        } 
        // Well the app will no longer be stopped.
        // Clear app token stopped state in window manager if needed.
        next.notifyAppResumed(next.stopped);
        next.sleeping = false;
        mService.getAppWarningsLocked().onResumeActivity(next);
next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
        next.clearOptionsLocked();
        // 触发onResume
       transaction.setLifecycleStateRequest(
		       ResumeActivityItem.obtain(next.app.getReportedProcState(), 
		       getDisplay().mDisplayContent.isNextTransitionForward()));
        mService.getLifecycleManager().scheduleTransaction(transaction); 
        // From this point on, if something goes wrong there is no way
        // to recover the activity.
        next.completeResumeLocked();
    } else {// 进程没启动
        // Whoops, need to restart this activity!
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        } else {
            if (SHOW_APP_STARTING_PREVIEW) {
                next.showStartingWindow(null, false, false);
            }
        }
        // 创建 App 进程并启动 Activity.
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    return true;
}

3.15 ActivityStackSupervisor.startSpecificActivityLocked

ActivityStackSupervisor.java

void startSpecificActivityLocked(ActivityRecord r, boolean andResume,
        boolean checkConfig) {
    final WindowProcessController wpc =
       mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    // 如果已经有进程,则调用 realStartActivityLocked,此处不会走,因为进程没启动
    if (wpc != null && wpc.hasThread()) {
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
       }
        knownToBeDead = true;
    }
	......
	try {
    	......
		// Post message to start process to avoid possible deadlock of 
		// calling into AMS with the ATMS lock held.
		// 关键调用,发送消息,启动进程
		final Message msg = PooledLambda.obtainMessage(
				ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
				r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
		mService.mH.sendMessage(msg);
	} finally {
		Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
	}
}

会在 try 中调用 ActivityManagerService 的 startProcess() 方法,从方法名可以看出,是启动一个新进程。

3.16 ActivityManagerService.startProcess

ActivityManagerService.java

public void startProcess(String processName, ApplicationInfo info,
        boolean knownToBeDead, String hostingType, ComponentName hostingName) {
    try {
        ......
        synchronized (ActivityManagerService.this) {
            startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                    new HostingRecord(hostingType, hostingName),
                    false /* allowWhileBooting */, false /* isolated */,
                    true /* keepIfLarge */);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

3.17 ActivityManagerService.startProcessLocked

ActivityManagerService.java

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        HostingRecord hostingRecord, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
            hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

3.18 ProcessList.startProcessLocked

ProcessList.java

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, ......) {
	......
	checkSlow(startTime, "startProcess: stepping in to startProcess");
	final boolean success = startProcessLocked(app, hostingRecord, abiOverride);
	checkSlow(startTime, "startProcess: done starting proc!");
	return success ? app : null;
}

final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
        String abiOverride) {
    return startProcessLocked(app, hostingRecord,
            false, false, abiOverride);
}

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
		boolean disableHiddenApiChecks, boolean mountExtStorageFull,
		String abiOverride) {
	......
	try {
		......
		final String seInfo = app.info.seInfo
				+ (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
		// 关键字符串,用于在新创建进程中的主线程中执行的类名称
		final String entryPoint = "android.app.ActivityThread";

		return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
				runtimeFlags, mountExternal, ......);
	} catch (RuntimeException e) {
		......
	}
}


boolean startProcessLocked(HostingRecord hostingRecord,
		String entryPoint,
		ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
		String seInfo, String requiredAbi, String instructionSet, String invokeWith,
		long startTime) {
	app.pendingStart = true;
	app.killedByAm = false;
	app.removed = false;
	app.killed = false;
	......

	if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
		if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
				"Posting procStart msg for " + app.toShortString());
		mService.mProcStartHandler.post(() -> {
			try {
			// 关键函数调用
				final Process.ProcessStartResult startResult = 
				startProcess(app.hostingRecord,
						entryPoint, app, app.startUid, gids, ......);
				synchronized (mService) {
					handleProcessStartedLocked(app, startResult, startSeq);
				}
			} catch (RuntimeException e) {
				......
			}
		});
		return true;
	} else {
		......
	}
}

3.19 ProcessList.startProcess

ProcessList.java

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord,
    String entryPoint,	ProcessRecord app,......) {
	try {
		......
		final Process.ProcessStartResult startResult;
		if (hostingRecord.usesWebviewZygote()) {
			......
		} else if (hostingRecord.usesAppZygote()) {
			......
		} else {
		// 调用 Process.start
			startResult = Process.start(entryPoint,
					app.processName, uid, uid, gids, runtimeFlags, mountExternal,
					app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
					app.info.dataDir, invokeWith, app.info.packageName,
					new String[] {PROC_START_SEQ_IDENT + app.startSeq});
		}
		checkSlow(startTime, "startProcess: returned from zygote!");
		return startResult;
	} finally {
		Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
	}
}

可以看到是通过调用 Process 的 start 方法来启动新进程的。至此进入新进程的创建阶段。

四 新进程创建阶段

接上一阶段,我们知道 ProcessList 内部经过一系列 startProcessLocked 的调用,最终会调用到 startProcess 函数。我们需要注意其中的 entryPoint 这个参数,这个参数会一路从 Process 传递到 ZygoteProcess,并在 ZygoteProcess 中调用 startViaZygote 方法,fork 出一个新的进程。并根据传递的 “android.app.ActivityThread” 反射出该对象,于是进程创建进入到 ActivityThread 的 main 方法中。这一部分的流程我们在之前 Android系统启动系列7 进程创建流程 中已经介绍过,在此不再赘述。

因为篇幅的原因,接下来的 onCreate,onStart,onResume 函数阶段,我们放在下一篇文章 Android四大组件系列3 Activity启动流程(下)中分析。

参考文档:
https://blog.csdn.net/songkai0825/article/details/111415462#t8
https://duanqz.github.io/2016-07-29-Activity-LaunchProcess-Part1#3-assstartactivitylocked
http://gityuan.com/2016/03/12/start-activity/

你可能感兴趣的:(Android,framework)