Android 源码分析之旅3.2--Activity启动流程(系统级API入门Framework)

为什么要学习源码?

这是源码分析系列的第三篇博客了,这里我说明一下为什么要进行Activity启动流程的源码分析。

学习源码有助于我们学习一些黑科技,比如学习插件化的从时候我们需要学习Hook机制,但是学习Hook机制的时候我们需要掌握Activity的启动流程、消息机制等等机制。

Activity启动流程分析

我们平常在Activity中调用startActivity(intent)来启动一个Activity的时候,通过调用链的分析,最终会调用Activity的startActivityForResult方法:

public void startActivityForResult(Intent intent, int requestCode, 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;
        }

        cancelInputsAndStartExitTransition(options);
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

这个方法实际会调用Instrumentation类的execStartActivity方法,Instrumentation类与Activity的初始化有关。Instrumentation类的execStartActivity方法如下:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    //IApplicationThread是一个AIDL接口,实现类是ActivityThread里的内部类ApplicationThread通过他可以进行进程间通信,通过ApplicationThread可以识别出一个进程。
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    //...省略一些代码
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        //ActivityManagerNative是一个AIDL接口的二分之一:Stub(存根)
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

ActivityManagerNative是一个AIDL接口的二分之一:Stub,与AMS进行通信的。ActivityManagerNative里面还有一个内部类ActivityManagerProxy。如下图所示:

因此到这里已经开始了进程间通信了,通过通知AMS去进行后续的处理。
之前已经分析过了,通过ActivityManagerNative.getDefault()得到的实质上是ActivityManagerNative与AMS进行通信的一个AIDL接口的引用:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        IActivityManager am = asInterface(b);
        return am;
    }
};

而实现这个接口的正是ActivityManagerNative的一个内部类ActivityManagerProxy:

class ActivityManagerProxy implements IActivityManager{
}

那么这个ActivityManagerProxy就是向AMS的IBinder写数据的,比如说启动Activity的时候就需要进行进程间通信了,我们把数据都放到可序列化的Parcel对象里面,写到IBinder驱动里面去。

下面是ActivityManagerProxy中startActivity的实现:

//caller代表着应用,调用者,比如说通过桌面启动Activity的话,caller就是代表着Launcher的描述。
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
        String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    //这里省略一些写数据的代码
    //调用transact方法向IBinder驱动写数据
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
    //读取跨进程通信的时候是否有异常
    reply.readException();
    int result = reply.readInt();
    //回收数据,防止内存泄漏
    reply.recycle();
    data.recycle();
    return result;
}

数据写到Binder驱动里面去之后就会回调ActivityManagerNative(也就是Stub)的onTransact方法,这个方法比较长,还包括很多其他的case,这里只抽取了一部分核心代码。
根据我们transact的code(START_ACTIVITY_TRANSACTION),可以过滤出下面的代码:

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
    case START_ACTIVITY_TRANSACTION:
    {
        data.enforceInterface(IActivityManager.descriptor);
        IBinder b = data.readStrongBinder();
        //将IBinder接口转换为AIDL的引用
        IApplicationThread app = ApplicationThreadNative.asInterface(b);
        String callingPackage = data.readString();
        //省略一些获取参数的代码
        //ActivityManagerNative的真正实现类是AMS,因此这里是调用AMS的startActivity方法
        int result = startActivity(app, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
        reply.writeNoException();
        reply.writeInt(result);
        return true;
    }
}

ActivityManagerNative的真正实现类是ActivityManagerService(AMS),AMS与四大组件的创建、传播、生命周期的管理里面起到了重要的作用。
这里是调用了AMS的startActivity方法:

@Override
public final int startActivity(...省略一些参数) {
    return startActivityAsUser(...省略一些参数);
}

而AMS的startActivity里面又会调用startActivityAsUser方法:

@Override
public final int startActivityAsUser(...省略一些参数) {
    //拿到启动的信息
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    //这里又会调用ActivityStarter的startActivityMayWait方法:
    return mActivityStarter.startActivityMayWait(...省略一些参数);
}

ActivityStackSupervisor是APP的栈的管理类,管理四大组件的栈的问题。而ActivityStarter就是每一个被管理的任务栈。分Task任务来管理,一个任务里面可能多个栈,别说当前正在使用、已停止的栈、历史栈。
ActivityStackSupervisor里面记录了一大堆Activity的记录:

final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<>();
final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<>();

这里又会调用ActivityStarter的startActivityMayWait方法:

final int startActivityMayWait(...省略一些参数) {
    mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
    boolean componentSpecified = intent.getComponent() != null;
    //封装出一个Intent来
    intent = new Intent(intent);
    //这里经历了一个PMS(PackageManagerService)对Intent的验证过程,验证这个Activity在清单文件里面是否有定义,这一步很重要,将来我们学习Hook机制免清单注册启动Activity的时候这是比较关键的
    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
    //省略一些代码
    //把目标的Activity的信息提取出来
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    //省略一些代码
    synchronized (mService) {
        //通过获取Binder获取我们启动这个Activity的进程id,Uid
        final int realCallingPid = Binder.getCallingPid();
        final int realCallingUid = Binder.getCallingUid();

        //省略一些代码
        final ActivityRecord[] outRecord = new ActivityRecord[1];
        //继续调用startActivityLocked方法:
        int res = startActivityLocked(...省略一些参数);
        //省略一些代码
    }
}

上面的函数里面比较重要的就是下面这一行代码:

ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);

这里调用了ActivityStackSupervisor的resolveIntent,通过调用链分析得到实际上是调用了下面这个方法:

ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
    try {
        return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY | flags
                | ActivityManagerService.STOCK_PM_FLAGS, userId);
    } catch (RemoteException e) {
    }
    return null;
}

我们平时启动Activity的时候,如果要检测有没有对应Activity的话,就需要resolveIntent方法。
这里PMS会去找清单文件,是否有注册的Activity,尤其是隐式意图启动Activity的时候。

下面我们看AppGlobals里面getPackageManager方法的定义,其返回的是IPackageManager,这是一个AIDL接口。

public static IPackageManager getPackageManager() {
    return ActivityThread.getPackageManager();
}

下面看看ActivityThread里面的getPackageManager方法,实际上就是一个“叫服务”的过程,实际就是拿到IBinder引用,然后通过asInterface方法转换为与PMS通信的AIDL接口的引用:

public static IPackageManager getPackageManager() {
    IBinder b = ServiceManager.getService("package");
    sPackageManager = IPackageManager.Stub.asInterface(b);
    return sPackageManager;
}

整个过程就是拿到PackageManager的AIDL引用,然后调用他的resolveIntent方法,而这个IPackageManager的实现类就是谁呢?不是PackageManager,因为他只是一个单独的类:

public abstract class PackageManager {
}

IPackageManager的真正实现类是PackageManagerService(PMS),这是一个系统服务:

public class PackageManagerService extends IPackageManager.Stub {
}

PackageManagerService里面的resolveIntent方法实现如下:

@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
        int flags, int userId) {
    try {
        //省略一些代码
        //查找是否存在这个Intent代表的Activity,返回的结果可能有多个
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                flags, userId);
        //选择最好(最符合条件)的一个Activity
        final ResolveInfo bestChoice =
                chooseBestActivity(intent, resolvedType, flags, query, userId);
        return bestChoice;
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

PackageManagerService在Android系统启动的时候就会启动,并且会扫描所有的已经安装的应用的清单文件,然后保存到内存当中。这里调用了queryIntentActivitiesInternal方法去找符合Intent过滤条件的Activity列表。
该方法的实现如下:

private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
        String resolvedType, int flags, int userId) {
    //省略一些代码
    //拿到Intent的Component
    ComponentName comp = intent.getComponent();
    //省略一些代码
    if (comp != null) {
        final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
        //通过组件名、flags、userId获取Activity信息
        final ActivityInfo ai = getActivityInfo(comp, flags, userId);
        if (ai != null) {
            final ResolveInfo ri = new ResolveInfo();
            ri.activityInfo = ai;
            //如果能够找到对应的Activity,就会添加到list里面去,最后返回
            list.add(ri);
        }
        return list;
    }
    //后面省略一些Intent先后排序的代码
    return result;
}

在PackageManagerService里面的resolveIntent方法最后,还会考虑到Intent的优先级问题,也就是调用chooseBestActivity,选择最好的Activity:

  1. 如果查询结果只有一个的话,那么直接返回第0个;否则需要处理优先级的问题。
  2. 否则如果我们只启动一个Activity的话,就要根据priority优先级来判断了。(所以清单文件里面有优先级的配置)。

下面我们稍微研究一些关于PMS的chooseBestActivity方法:

private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
        int flags, List<ResolveInfo> query, int userId) {
    if (query != null) {
        final int N = query.size();
        //如果查询结果只有一个的话,那么直接返回第0个;否则需要处理优先级的问题
        if (N == 1) {
            return query.get(0);
        } else if (N > 1) {
            ResolveInfo r0 = query.get(0);
            ResolveInfo r1 = query.get(1);
            //如果我们只启动一个Activity的话,就要根据priority优先级来判断了。(所以清单文件里面有优先级的配置)
            if (r0.priority != r1.priority
                    || r0.preferredOrder != r1.preferredOrder
                    || r0.isDefault != r1.isDefault) {
                return query.get(0);
            }
            //省略一些代码
        }
    }
    return null;
}

也就是说这里系统通过PMS去做了一个验证,判断清单文件里面是否有这个Activity,并且返回最好的一个。

PMS主要用来管理包的信息,而包的信息保存在清单文件。例如他回去/data/data目录去扫描。例如在PMS构造的时候你会发现这些代码:

public PackageManagerService(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    synchronized (mPackages) {
        //需要扫描的目录
        File dataDir = Environment.getDataDirectory();
        //data/data/app:第三方APP的安装目录
        mAppInstallDir = new File(dataDir, "app");
        mAppLib32InstallDir = new File(dataDir, "app-lib");
        mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
        mAsecInternalPath = new File(dataDir, "app-asec").getPath();
        //data/data/app-private:系统APP的安装目录
        mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
        if (!mOnlyCore) {
            //调用scanDirLI去扫描
            scanDirLI(mEphemeralInstallDir, mDefParseFlags
                    | PackageParser.PARSE_IS_EPHEMERAL,
                    scanFlags | SCAN_REQUIRE_KNOWN, 0);
            }
        }
}

PMS的scanDirLI方法如下:

private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
    final File[] files = dir.listFiles();
    for (File file : files) {
        //扫描,判断是不是APK文件
        final boolean isPackage = (isApkFile(file) || file.isDirectory())
                && !PackageInstallerService.isStageName(file.getName());
        if (!isPackage) {
            continue;
        }
        try {
            //然后去解析APK的清单文件,把四大组件的信息、权限等解析出来
            scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
                    scanFlags, currentTime, null);
        } catch (PackageManagerException e) {
        }
    }
}

一开机的时候,SystemServer启动之后就会启动PMS,就会调用PMS的main方法,把自己注册到ServiceManager里面去:
ServiceManager就是我们的服务总台,保存所有服务的“联系方式”。

public static PackageManagerService main(...省略一些参数) {
    PackageManagerServiceCompilerMapping.checkProperties();

    //new一个PMS,PMS在构造方法的时候就会去扫描清单文件
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    m.enableSystemUserPackages();
    //把自己注册到ServiceManager里面去
    ServiceManager.addService("package", m);
    return m;
}

我们回到ActivityStarter的startActivityMayWait方法,继续走会发现调用了startActivityLocked方法:

//继续调用startActivityLocked方法:
int res = startActivityLocked(...省略一些参数);

这是ActivityStarter的startActivityLocked方法:

final int startActivityLocked(...省略一些参数) {
    //初始化了一个错误标志,常见的错误有很多,比如:找不到Activity,Activity没有在清单文件中注册等等
    int err = ActivityManager.START_SUCCESS;

    //获取调用者的一些信息
    ProcessRecord callerApp = null;
    if (caller != null) {
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    //省略一些代码
    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
        //错误:找不到Activity的意图
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

    if (err == ActivityManager.START_SUCCESS && aInfo == null) {
        //错误:找不到Activity的Class类,比如说清单文件里面的类名写错了
        err = ActivityManager.START_CLASS_NOT_FOUND;
    }

    //省略一些代码

    //省略验证权限相关的代码,因为一个Activity的启动可能需要一些权限,尤其是自定义权限的时候
    if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
        if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                aInfo.packageName, userId)) {
        }
    }

    //如果没有错误信息的话,就会创建一个ActivityRecord,记录着Activity的各种信息,例如返回结果的时候需要跳到哪个Activity的信息,Activity所在的进程(例如启动一个没有进程的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);
    //省略一些代码

    try {
        mService.mWindowManager.deferSurfaceLayout();
        //调用startActivityUnchecked,无需检查,真正去启动
        err = startActivityUnchecked(...省略一些参数);
    } finally {
        mService.mWindowManager.continueSurfaceLayout();
    }
    postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
    return err;
}

调用startActivityUnchecked,无需检查其他东西去启动Activity:
这个方法处理了Activity的启动模式,比如是否需要新建一个任务栈,栈里面是否需要复用已经存在的Activity实例等等。而且启动模式还要配合flag,比如说NEW_TASK等。
并且在清单文件里面的启动模式的配置要优先于flags。

private int startActivityUnchecked(...省略一些参数) {
    //省略一些代码
    if (mReusedActivity != null) {
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || mLaunchSingleInstance || mLaunchSingleTask) {
            //查询顶端的Activity
            final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
                    mStartActivity, mLaunchFlags);
            if (top != null) {
                if (top.frontOfTask) {    
                    top.task.setIntent(mStartActivity);
                }
                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
                top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                        mStartActivity.launchedFromPackage);
            }
        }
        //省略一些代码
    }

    if (mStartActivity.packageName == null) {
        if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
            mStartActivity.resultTo.task.stack.sendActivityResultLocked(
                    -1, mStartActivity.resultTo, mStartActivity.resultWho,
                    mStartActivity.requestCode, RESULT_CANCELED, null);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }
    //省略一些代码
    //调用目标的Activity栈的startActivityLocked方法
    mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
    //省略一些代码
}

Activity任务栈(Task)

任务栈里面存放着ActivityRecord,是一种后进先出的数据结构。
比如Launcher去启动Activity的时候,就需要新建一个任务栈。调用系统的应用的时候,比如相机,如果不指定NEW_TASK,就会在自己的APP的任务栈里面启动。
比较特殊的就是单例模式,就是会新建一个任务栈。
栈也有顺序的,我们看到的是正在显示的栈,退出这个栈以后,就会显示下一个栈。

在上面的方法的最后会调用目标的Activity栈的startActivityLocked方法:

//调用目标的Activity栈的startActivityLocked方法
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
  1. ActivityStackSupervisor:APP的栈的管理类(管理的时候也是用栈的模型),比如哪个任务栈需要显示,Activity需要选择哪个栈去进栈,并且检查Intent的flags。
  2. ActivityStack:就是一个个被ActivityStackSupervisor管理的栈,管理者Activity。

下面我们分析ActivityStack的startActivityLocked:

final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
        ActivityOptions options) {
    //找到需要启动的Activity的任务栈,因为每一个Activity一定会分配一个任务栈
    TaskRecord rTask = r.task;
    //那大任务栈的ID
    final int taskId = rTask.taskId;
    // mLaunchTaskBehind tasks get placed at the back of the task stack.
    if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
        //如果不是后置任务(某些Activity进栈之后还要处理一些操作),那就把这个任务栈加到最顶端,也就是成为有焦点的栈
        //告诉WindowManager,把Task移到顶部,因为窗口的显示是由WindowManager来控制的。并且显示这个任务栈里面最顶部的Activity。
        insertTaskAtTop(rTask, r);
        mWindowManager.moveTaskToTop(taskId);
    }
    TaskRecord task = null;
    if (!newTask) {
        //如果不需要启动一个新的任务栈的话,直接重复利用当前的Task
        boolean startIt = true;
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            task = mTaskHistory.get(taskNdx);
            if (task.getTopActivity() == null) {
                // All activities in task are finishing.
                continue;
            }
            if (task == r.task) {
                if (!startIt) {
                    //如果不需要启动一个新的任务栈,直接把Activity添加到当前最顶部的TASK,并且放到顶部
                    task.addActivityToTop(r);
                    //添加到回退栈
                    r.putInHistory();
                    //省略一些代码
            } else if (task.numFullscreen > 0) {
                startIt = false;
            }
        }
    }

    //需要新建一个任务栈的话,就新建一个,然后添加Activity,通知WM,具体代码就不看了。
    if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
        mStackSupervisor.mUserLeaving = false;
    }
    task = r.task;
    task.addActivityToTop(r);
    task.setFrontOfTask();
    //...省略一些代码
    if (doResume) {
        mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
    }
}

接着调用ActivityStackSupervisor的resumeTopActivitiesLocked,下面继续分析:

boolean resumeTopActivitiesLocked() {
    return resumeTopActivitiesLocked(null, null, null);
}

根据调用关系链,会调用下面这个方法:

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
        Bundle targetOptions) {
    //省略一些代码
    if (isFrontStack(targetStack)) {
        //调用ActivityStack的resumeTopActivityLocked方法查找需要暂停的Activity
        result = targetStack.resumeTopActivityLocked(target, targetOptions);
    }
    //省略一些代码
}

ActivityStack的resumeTopActivityLocked如下:

final boolean resumeTopActivityLocked(ActivityRecord prev) {
    return resumeTopActivityLocked(prev, null);
}

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    //省略一些代码
    try {
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        inResumeTopActivity = false;
    }
    return result;
}

然后调用resumeTopActivityInnerLocked:

final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    //省略一些代码
    //找到第一个没有被销毁的Activity,根据ActivityStackSupervisor的成员变量所保存的数组来查找
    //所找到的Activity将来准备要进入暂停状态
    //我们的APP所有Activity任务栈统一通过进程通信交给ActivityStackSupervisor管理所有任务栈。
    //因为ActivityStackSupervisor知道整个系统的哪个进程死了,需要显示哪个任务栈
    ActivityRecord next = topRunningActivityLocked(null);

    //省略一些代码
    //需要把当前准备暂停的Activity,从一些状态数组里面移除
    mStackSupervisor.mStoppingActivities.remove(next);
    mStackSupervisor.mGoingToSleepActivities.remove(next);
    next.sleeping = false;
    mStackSupervisor.mWaitingVisibleActivities.remove(next);

    //调用startPausingLocked暂停最顶部的Activity,通过这样做的话,它将来就能够复活resume
    boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
    if (mResumedActivity != null) {
        pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
    }
 
    //省略一些代码
    ActivityStack lastStack = mStackSupervisor.getLastStack();
    //一个Activity要启动的话,需要先判断app以及thread还存不存在,如不存在就需要重新创建一个进程。
    //比如说从launcher启动Activity
    if (next.app != null && next.app.thread != null) {
        //无需创建进程
    } else {
        //需要启动的的Activity还没有启动对应的进程,需要去启动进程
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        } else {
        //省略一些代码
        //重新启动进程
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    return true;
}

startPausingLocked:

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
        boolean dontWait) {
  
    //找到上一个需要暂停的Activity
    ActivityRecord prev = mResumedActivity;
    if (prev == null) {
        if (!resuming) {
            mStackSupervisor.resumeTopActivitiesLocked();
        }
        return false;
    }

    //先判断之前的Activity是否存在,如果存在,需要进行进程间通信,通知那个app去停止Activity
    //之所以每一个Activity都需要用一个ActivityRecord去记录,就是因为需要记录每一个Activity所在进程等等信息,方便系统去管理
    if (prev.app != null && prev.app.thread != null) {
        try {
            EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                    prev.userId, System.identityHashCode(prev),
                    prev.shortComponentName);
            mService.updateUsageStats(prev, false);
            //如果存在,需要进行进程间通信,通知那个app去停止Activity
            prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                    userLeaving, prev.configChangeFlags, dontWait);
        } catch (Exception e) {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
    } 
    //省略一些代码
}

schedulePauseActivity方法会发起进程间通信,通知即将要停止的Activity所在的进程,去暂停这个Activity。最终会在那个进程的ActivityThread里面回调schedulePauseActivity方法:
实质上就是发送消息给Handler,然后调用,去停止Activity。

public final void schedulePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport) {
    int seq = getLifecycleSeq();
    //省略一些代码
    sendMessage(
            finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
            token,
            (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
            configChanges,
            seq);
}

Handler里面的case如下:

case PAUSE_ACTIVITY: {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    SomeArgs args = (SomeArgs) msg.obj;
    handlePauseActivity((IBinder) args.arg1, false,
            (args.argi1 & USER_LEAVING) != 0, args.argi2,
            (args.argi1 & DONT_REPORT) != 0, args.argi3);
    maybeSnapshot();
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;

handlePauseActivity:

private void handlePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport, int seq) {
    ActivityClientRecord r = mActivities.get(token);
    if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
        return;
    }
    if (r != null) {
        if (userLeaving) {
            performUserLeavingActivity(r);
        }

        r.activity.mConfigChangeFlags |= configChanges;
        //真正去执行暂停Activity
        performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

        // Tell the activity manager we have paused.也就是说,先停止,然后回馈给AMS的activityPaused方法
        if (!dontReport) {
            try {
                ActivityManagerNative.getDefault().activityPaused(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
        mSomeActivitiesChanged = true;
    }
}

performPauseActivity:

final Bundle performPauseActivity(IBinder token, boolean finished,
        boolean saveState, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}

然后又会调用performPauseActivity:

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
        boolean saveState) {
    //省略一些代码
    try {
        //省略一些代码

        //真正去停止Activity
        mInstrumentation.callActivityOnPause(r.activity);
        EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
                r.activity.getComponentName().getClassName());
        if (!r.activity.mCalled) {
            throw new SuperNotCalledException(
                "Activity " + r.intent.getComponent().toShortString() +
                " did not call through to super.onPause()");
        }

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
    }
}

然后:

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

最后回调Activity的onPause方法

final void performPause() {
    //省略一些代码
    onPause();
    //省略一些代码
}

在handlePauseActivity的最后还要:

// Tell the activity manager we have paused.也就是说,先停止,然后回馈给AMS的activityPaused方法
// 这就解释了为什么新启动的Activity启动之前,旧的先onPause
if (!dontReport) {
    try {
        ActivityManagerNative.getDefault().activityPaused(token);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

@Override
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    synchronized(this) {
        //AMS去启动栈顶部Activity
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
    Binder.restoreCallingIdentity(origId);
}

ActivityStackSupervisor、ActivityStack只是管理了Activity的栈,栈放什么,而真真正正去处理四大组件启动的还是AMS服务。之前的一系列操作只是进行了一些栈的管理操作,然后通知APP进程暂停,然后APP进程再去通知AMS去启动栈顶部Activity。

//Activity已经暂停了
final void activityPausedLocked(IBinder token, boolean timeout) {
    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
        if (mPausingActivity == r) {
            //然后调用completePauseLocked,表示上一个Activity已经停止完成了,然后resume要启动的Activity
            completePauseLocked(true);
        }
    }
}

然后调用completePauseLocked,表示上一个Activity已经停止完成了,然后resume要启动的Activity:

private void completePauseLocked(boolean resumeNext) {
    ActivityRecord prev = mPausingActivity;
    //省略一些代码
    if (resumeNext) {
        //拿到顶部任务栈
        final ActivityStack topStack = mStackSupervisor.getFocusedStack();
        if (!mService.isSleepingOrShuttingDown()) {
            mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
        } 
    }
    //省略一些代码
}

然后调用:

boolean resumeTopActivitiesLocked() {
    return resumeTopActivitiesLocked(null, null, null);
}

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
        Bundle targetOptions) {
    //省略一些代码
    if (isFrontStack(targetStack)) {
        result = targetStack.resumeTopActivityLocked(target, targetOptions);
    }
    //省略一些代码
}

又会回来调用ActivityStack的resumeTopActivityLocked,里面继续调用resumeTopActivityInnerLocked:

    if (next.app != null && next.app.thread != null) {
        //不需要启动进程
    } else {
        //需要启动进程
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        }
        //省略一些代码
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }

先判断app的进程有没有启动,例如连续启动。

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    //省略一些代码
    if (app != null && app.thread != null) {
        //不需要启动进程
    }

    //启动进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

调用AMS的方法来启动进程:

//看到hosting,证明Java准备跟底层的C/C++通信了
final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(...省略一些参数);
}

final ProcessRecord startProcessLocked(...省略一些参数) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    //省略一些代码
    //创建app对象,但是这时候进程还没启动
    //省略一些代码
    if (app == null) {
        checkTime(startTime, "startProcess: creating new process record");
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
    } 
    //启动进程
    startProcessLocked(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
}

启动进程:

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    long startTime = SystemClock.elapsedRealtime();
    //省略一些代码
    try {
        if (!app.isolated) {
            //省略一些代码
            //获取PID、UID
            gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
            gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
        }
        checkTime(startTime, "startProcess: building args");
        if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                    && mTopComponent != null
                    //获取包名
                    && app.processName.equals(mTopComponent.getPackageName())) {
                uid = 0;
            }
        }
        int debugFlags = 0;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            //开始配置Zygote进程
            debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
            // Also turn on CheckJNI for debuggable apps. It's quite
            // awkward to turn on otherwise.
            debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
        }
        //省略一些代码
        //android.app.ActivityThread是Java层的入口类
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        //开始启动进程
        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);

        //开始拼装启动的脚本,最后写到C/C++里面
        StringBuilder buf = mStringBuilder;
        buf.setLength(0);
        buf.append("Start proc ");
        buf.append(startResult.pid);
        buf.append(':');
        buf.append(app.processName);
        buf.append('/');
        //省略一些脚本的拼装
        synchronized (mPidsSelfLocked) {
            this.mPidsSelfLocked.put(startResult.pid, app);
            if (isActivityProcess) {
                //把这些信息拼装成一个消息,然后通过Handler来处理,最后是跟底层通信,通过C/C++的方式去启动进程
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
        }
    } catch (RuntimeException e) {
    }
}

最后ActivityThread会启动,启动ActivityThread的main方法:

public static void main(String[] args) {
    //省略一些代码
    Environment.initForCurrentUser();

    Process.setArgV0("<pre-initialized>");

    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    //把当前进程attach到系统中
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    Looper.loop();

}

如下:

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //调用IActivityManager,通过进程间通信,绑定Application。IActivityManager的实现类是AMS
            //查看AMS的实现之后,又会调用attachApplicationLocked,然后又会调用ActivityStackSupervisor的attachApplicationLocked
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
        }
    } 
    //省略一些代码
}

AMS的attachApplicationLocked方法有一句核心代码如下,然后又会调用ActivityStackSupervisor的attachApplicationLocked:

//如果进程已经启动了,而且在栈顶部有一个属于这个进程的Activity需要启动
if (normalMode) {
    try {
        if (mStackSupervisor.attachApplicationLocked(app)) {
            didSomething = true;
        }
    } catch (Exception e) {
        Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
        badApp = true;
    }
}

进程被创建,不一定需要Activity的启动。Activity跟进程还没有关联,因此realStartActivityLocked:

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    for (...省略) {
        ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        for (...省略) {
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        //继续调用realStartActivityLocked
                        if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
                    }
                }
            }
        }
    }
}

realStartActivityLocked里面有这样一句:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                    results, newIntents, !andResume, mService.isNextTransitionForward(),
                    profilerInfo);

通过进程间通信,回到APP的ActivityThread,发送消息给H,然后启动:

case LAUNCH_ACTIVITY: {
    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

    r.packageInfo = getPackageInfoNoCheck(
            r.activityInfo.applicationInfo, r.compatInfo);
    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
} break;

然后:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    //省略一些代码
    //先初始化窗口
    WindowManagerGlobal.initialize();

    //然后performLaunchActivity
    Activity a = performLaunchActivity(r, customIntent);

    //省略一些代码
}

performLaunchActivity:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }

    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }

    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }

    Activity activity = null;
    try {

        //通过反射的方式去创建Activity
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
    }

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (activity != null) {
          
            //省略一些代码
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                //设置主题
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            //回调OnCreate
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                //回调onStart、onResum等
                activity.performStart();
                r.stopped = false;
            }
        }

    } catch (SuperNotCalledException e) {

    } catch (Exception e) {
    }

    return activity;
}

关于newActivity:

public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}

几个有关的核心类

  1. ActivityManagerService(本地Stub是ActivityManagerNative):系统进程里面的一个服务,管理四大组件的生命周期等等。
  2. ActivityThread:Android应用程序的Java层入口函数。
  3. PackageManagerService:清单的扫描、注册。
  4. ActivityStackSupervisor:管理所有任务栈,是通过栈的模型去管理的,是否需要新建任务栈?等等。
  5. ActivityStack:任务栈,管理任务栈里面的Activity。
  6. WindowManager:只管理当前最顶部的栈的Activity的UI的渲染。

Activity的启动总结如下:

Activity启动过程

这里先对这个图进行一些必要的说明:

  1. 这是MyActivity的启动流程,流程是从左边开始,逆时针旋转。主要展示了Application怎么调到Android System Service,Android System Service如何反过来调Application。
  2. Instrumentation是Activity的一个成员,这里用聚合表示。Instrumentation用于记录Activity的一切操作。
  3. Application以及H都是ActivityThread的内部类
  4. ActivityManagerService,简称AMS,是Android系统服务中的一个核心模块,其他的还有WindowsManagerService(WMS)、PackageManagerService(PMS)、NotificationManagerService(NMS)等等。AMS主要的功能是管理应用进程以及应用进程中的组件、内存管理。
  5. 从上面的图可以看出Android系统的几个明显的层次关系。

思想

  1. 大量采用了C/S架构,交给远程进程统一管理,这样才能够实现多进程,多窗口,有条不紊。
  2. 模块化的思想,不同的模块管理不同的东西。多建立package,分模块,比如说网络访问专门一个包。
  3. 分层次思想,不能一个类所有事情都管理了。

如果觉得我的文字对你有所帮助的话,欢迎关注我的公众号:

公众号:Android开发进阶

我的群欢迎大家进来探讨各种技术与非技术的话题,有兴趣的朋友们加我私人微信huannan88,我拉你进群交(♂)流(♀)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容