Android Launcher启动应用程序流程源码解析

带着问题看源码

  1. 点击桌面Launcher图标后做了哪些工作?
  2. 应用程序什么时候被创建的?
  3. Application和MainActivity的onCreate()方法什么时候被调用的?

概述

在Android系统中,启动四大组件中的任何一个都可以启动应用程序。但绝大部分时候我们是通过点击Launcher图标启动应用程序。本文依据Android6.0源码,从点击Launcher图标,直至解析到MainActivity#OnCreate()被调用。

Launcher简析

Launcher也是个应用程序,不过是个特殊的应用。俗称“桌面”。通过PackageManagerService查询所有已安装的应用程序,并保存相应的图标、应用名称、包名和第一个要启动的类名等。

源码位置:frameworks/base/core/java/android/app/LauncherActivity.java

LauncherActivity#onListItemClick()

public abstract class LauncherActivity extends ListActivity {
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }
}

可以看到LauncherActivity继承自ListActivity,而ListActivity继承自Activity。在LauncherActivity#onListItemClick()方法中首先通过intentForPosition()获取了一个Intent,然后调用startActivity(intent)启动一个Activity。由于ListActivity并没有重写Activity#startActivity()方法,所以这里会直接调用Activity#startActivity()。在此之前先看下intentForPosition()是怎样构造Intent

    protected Intent intentForPosition(int position) {
        ActivityAdapter adapter = (ActivityAdapter) mAdapter;
        return adapter.intentForPosition(position);
    }

    private class ActivityAdapter extends BaseAdapter implements Filterable {
        public Intent intentForPosition(int position) {
            if (mActivitiesList == null) {
                return null;
            }
            Intent intent = new Intent(mIntent);
            ListItem item = mActivitiesList.get(position);
            intent.setClassName(item.packageName, item.className);
            if (item.extras != null) {
                intent.putExtras(item.extras);
            }
            return intent;
        }
    }

Intent中只是指定了即将启动的Activity

源码位置:frameworks/base/core/java/android/app/Activity.java

Activity#startActivity()

    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);
        }
    }

    /** @param requestCode If >= 0, this code will be returned inonActivityResult() when the activity exits. */
    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
            Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
           ...
        }
    }

在调用的过程中可以观察到,无论调用StartActivity()还是startActivityForResult(),最终调用的都是startActivityForResult()。而且注释说明只有requestCode >= 0onActivityResult()才会被调用。经过一系列的调用,最终调用了Instrumentation#execStartActivity()。跟进。

源码位置:frameworks/base/core/java/android/app/Instrumentation.java

Instrumentation#execStartActivity()

    public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target, 
        Intent intent, int requestCode, Bundle options) {
            ...
            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简析,不想了解的也可以直接理解为返回的是ActivityManagerService(以下简称AMS)。实际调用的是AMS#startActivity()

AMS中Binder机制简析

ActivityManagerNative.getDefault()

    static public IActivityManager getDefault() {
        return gDefault.get();
    }

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

    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

本例中AMS作为服务器端,ActivityManagerNative作为客户端。在getDefault()方法中通过调用asInterface()方法中的 new ActivityManagerProxy(obj)返回了IActivityManager的子类对象AMS。从哪里可以看出来呢?这个就比较难找了,不过细心点还是可以发现写蛛丝马迹。重点在于IBinder b = ServiceManager.getService("activity"),这里的参数是“activity”。在上篇博文SystemServer启动流程源码解析中,分析SystemServer#startBootstrapServices()方法启动AMS之后调用mActivityManagerService.setSystemProcess(),跟进。

源码位置:frameworks/base/services/java/com/android/server/SystemServer.java

SystemServer#startBootstrapServices()

    private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        // Set up the Application instance for the system process and get started.
        mActivityManagerService.setSystemProcess();
    }

    public void setSystemProcess() {
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
    }

静态常量Context.ACTIVITY_SERVICE = "activity"。到这里就对上了。先addService("activity"),然后getService("activity")。其实在add和get的时候,又是一次通过Binder进行进程间通信的过程。这次和本文关系不大,这里不再拓展。下面回到AMS#startActivity()

调用过程解析

前方高能,可能会导致身体感到严重不适。请做好心理准备!

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#startActivity()

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        // 验证CallingUid是否合法
        enforceNotIsolatedCaller("startActivity");
        // 检查限权
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

简单验证后开始调用StackSupervisor#startActivityMayWait(),跟进。
源码位置:frameworks/base/services/core/java/com/android/server/am/StackSupervisor.java

StackSupervisor#startActivityMayWait()、StackSupervisor#resolveActivity()

    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, WaitResult outResult, Configuration config,
                                   Bundle options, boolean ignoreTargetSecurity, int userId,
                                   IActivityContainer iContainer, TaskRecord inTask) {
          ...
         // 解析intent信息                         
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
         // 验证pid uid(省略)
         ...
        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);

        return res;                          
    }

    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
                                 ProfilerInfo profilerInfo, int userId) {
        // Collect information about the target of the Intent.
        ActivityInfo aInfo;
        try {
            ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent(
                            intent, resolvedType,
                            PackageManager.MATCH_DEFAULT_ONLY 
                            | ActivityManagerService.STOCK_PM_FLAGS, userId);
            aInfo = rInfo != null ? rInfo.activityInfo : null;
        } catch (RemoteException e) {
            aInfo = null;
        }

        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            ...
        }
        return aInfo;
    }

在调用resolveActivity()之后会读取配置文件中包名和要启动Activity完整的路径名,并分别赋值给aInfo.applicationInfo.packageName和aInfo.name。跟进。

StackSupervisor#startActivityLocked()

    final int startActivityLocked(IApplicationThread caller,
                                  Intent intent, String resolvedType, ActivityInfo aInfo,
                                  IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                  IBinder resultTo, String resultWho, int requestCode,
                                  int callingPid, int callingUid, String callingPackage,
                                  int realCallingPid, int realCallingUid, int startFlags, Bundle options,
                                  boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
                                  ActivityContainer container, TaskRecord inTask) {
        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;
            }
        }
        ...
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, this, container, options);
        // 检查intent中的flag信息
        ...
        // 检查限权
        ...
        ...
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
        return err;

    }

这个方法近300行代码,我们只看关键的部分就好了。首先获取调用者的pid、uid等信息,然后保存在callerApp中。目标Activity的信息保存在 r 中。跟进。

StackSupervisor#startActivityUncheckedLocked()

    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
        boolean doResume, Bundle options, TaskRecord inTask) {
        ...
        int launchFlags = intent.getFlags();
        // 对intent的flag各种判断
        ...
        ActivityRecord notTop = (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
        ...
                ActivityStack sourceStack;
        if (sourceRecord != null) {
            if (sourceRecord.finishing) {
                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                    newTaskInfo = sourceRecord.info;
                    newTaskIntent = sourceRecord.task.intent;
                }
                sourceRecord = null;
                sourceStack = null;
            } else {
                sourceStack = sourceRecord.task.stack;
            }
        } else {
            sourceStack = null;
        }
        ...
        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || launchSingleInstance || launchSingleTask) {
            if (inTask == null && r.resultTo == null) {
                // See if there is a task to bring to the front.  If this is
                // a SINGLE_INSTANCE activity, there can be one and only one
                // instance of it in the history, and it is always in its own
                // unique task, so we do a special search.
                ActivityRecord intentActivity = !launchSingleInstance ?
                        findTaskLocked(r) : findActivityLocked(intent, r.info);
        ...
        }
        ...
        // Should this be considered a new task?
        if (r.resultTo == null && inTask == null && !addingToTask
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            targetStack = computeStackFocus(r, newTask);
            targetStack.moveToFront("startingNewTask");

            if (reuseTask == null) {
                // 设任务栈
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                        taskToAffiliate);
            } 
            ...
        }
        ...
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        return ActivityManager.START_SUCCESS;
    }

这个方法600+行,而且好多逻辑判断,看的几近崩溃。不过还好,关键的代码已经被过滤出来了~首先确定几个变量。前面都没有设置过intentflag,所以launchFlags = 0x00000000,但是在执行launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK之后。launchFlags = Intent.FLAG_ACTIVITY_NEW_TASKnotTop = null。由于没有要接收返回信息的Activity,所以r.resultTo == null。由于没有设置Activity的启动模式为SingleInstance,所以launchSingleInstance = false,即会执行findTaskLocked(r)。这个方法的作用是查找历史所有stack中有没有目标Activity,很显然返回值为null,所以下面很大一段判断逻辑都不会执行。大约200行,爽~。既然没有相应的任务栈,肯定要创建的。在上文中创建任务栈对应的方法为targetStack.createTaskRecord()。最后执行ActivityStack#startActivityLocked(),跟进。

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

ActivityStack#startActivityLocked()

    final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        ...
        // newTask = true
        if(!newTask){
            ...
        }
        task = r.task;
        // 将ActivityRecord置于栈顶
        task.addActivityToTop(r);
        // 将任务栈置于前台
        task.setFrontOfTask();
        ...
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

跟进。

源码位置:frameworks/base/services/core/java/com/android/server/am/StackSupervisor.java

StackSupervisor#resumeTopActivitiesLocked()

    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
                                      Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

这个方法的作用是将Launcher应用程序所在的任务栈执行resumeTopActivityLocked()方法。跟进。

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

ActivityStack#resumeTopActivityLocked()

    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

跟进。

ActivityStack#resumeTopActivityInnerLocked()

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        ...
        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
            ...
            return false;
        }
        ...
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }
        ...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
        ...
    }

这个方法的主要作用是将mResumedActivity暂停(Launcher任务栈的TopActivity),即进入onPause状态。之后启动指定的AttivityRecored,即target AttivityRecored

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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

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

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

由于没有在指定Applicationprocess属性,所以这里的app = null

详见ActivityStackSupervisor#getProcessRecordLocked()

    final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
        if (uid == Process.SYSTEM_UID) {
            // The system gets to run in any process.  If there are multiple
            // processes with the same uid, just pick the first (this
            // should never happen).
            SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName);
            if (procs == null) return null;
            ...
        }
        ...
    }

跟进。

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#startProcessLocked()

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

跟进。

ActivityManagerService#startProcessLocked()

    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        // isolated = false
        if (!isolated) {
            // 没有指定application的process,所以app = null
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            ...
        }
        ...
        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            // 创建ProcessRecord
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            ...
            checkTime(startTime, "startProcess: done creating new process record");
        }
    }
        ...
        checkTime(startTime, "startProcess: stepping in to startProcess");
        // hostingNameStr="activity" 后面仨参数都是null
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");

终于看见Process的身影了,亲人呐!!!

ActivityManagerService#startProcessLocked()

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            ...
        try {
            int uid = app.uid;
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            // isolated = false
            if (!app.isolated) {
                int[] permGids = null;
                try {
                    checkTime(startTime, "startProcess: getting gids from package manager");
                    final IPackageManager pm = AppGlobals.getPackageManager();
                    permGids = pm.getPackageGids(app.info.packageName, app.userId);
                    MountServiceInternal mountServiceInternal = LocalServices.getService(
                            MountServiceInternal.class);
                    mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
                            app.info.packageName);
                } catch (RemoteException e) {
                    throw e.rethrowAsRuntimeException();
                }

                /*
                 * Add shared application and profile GIDs so applications can share some
                 * resources like shared libraries and access user-wide resources
                 */
                if (ArrayUtils.isEmpty(permGids)) {
                    gids = new int[2];
                } else {
                    gids = new int[permGids.length + 2];
                    System.arraycopy(permGids, 0, gids, 2, permGids.length);
                }
                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
                gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
            }
            ...
            String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
            if (requiredAbi == null) {
                requiredAbi = Build.SUPPORTED_ABIS[0];
            }

            String instructionSet = null;
            if (app.info.primaryCpuAbi != null) {
                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
            }

            app.gids = gids;
            app.requiredAbi = requiredAbi;
            app.instructionSet = instructionSet;

            checkTime(startTime, "startProcess: asking zygote to start proc");
            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!");
            ...
        }
        ...
    }

这个方法太重要了,所以展示的代码稍微多一些。首先确定几个参数值。hostingType = activity、后面的三个参数abiOverrideentryPointentryPointArgs均等于nullapp.isolated = false。首先创建了gids[]这个参数,然后在前两项插入AppGidUserGid,然后构造了requiredAbiinstructionSet等参数,之后调用Process#start()来创建新进程。Process#start()。现在是凌晨两点,如果你像我一样已经写了5个小时,一定会发现这方法名字是多么的让人陶醉~

抽只烟冷静下~

跟进。

源码位置:frameworks/base/core/java/android/os/Process.java

Process#start()

    public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

这是只是调用startViaZygote()进一步处理。跟进。

Process#startViaZygote()

    private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
            ArrayList<String> argsForZygote = new ArrayList<String>();

            // --runtime-args, --setuid=, --setgid=,
            // and --setgroups= must go first
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            ...
                        // --setgroups is a comma-separated list
            if (gids != null && gids.length > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append("--setgroups=");

                int sz = gids.length;
                for (int i = 0; i < sz; i++) {
                    if (i != 0) {
                        sb.append(',');
                    }
                    sb.append(gids[i]);
                }

                argsForZygote.add(sb.toString());
            }

            if (niceName != null) {
                argsForZygote.add("--nice-name=" + niceName);
            }

            if (seInfo != null) {
                argsForZygote.add("--seinfo=" + seInfo);
            }

            if (instructionSet != null) {
                argsForZygote.add("--instruction-set=" + instructionSet);
            }

            if (appDataDir != null) {
                argsForZygote.add("--app-data-dir=" + appDataDir);
            }

            argsForZygote.add(processClass);

            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

可以看到,这里前面一大段都在构造参数argsForZygoteuid啦、gid啦、-nice-name啦,这里需要注意processClass = android.app.ActivityThread,后文会用到。参数构造完成之后,接下来看下openZygoteSocketIfNeeded()这个方法。

Process#openZygoteSocketIfNeeded()

    /**
     * Tries to open socket to Zygote process if not already open. If
     * already open, does nothing.  May block and retry.
     */
    private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
        }

        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }

        // The primary zygote didn't match. Try the secondary.
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
            secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
            }
        }

        if (secondaryZygoteState.matches(abi)) {
            return secondaryZygoteState;
        }

        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }

罕见的我把注释写上了,因为注释说的比我清楚~接下来跟进zygoteSendArgsAndGetResult()方法。

Process#zygoteSendArgsAndGetResult()

    /**
     * Sends an argument list to the zygote process, which starts a new child
     * and returns the child's pid. Please note: the present implementation
     * replaces newlines in the argument list with spaces.
     *
     * @throws ZygoteStartFailedEx if process start failed for any reason
     */
    private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            /**
             * See com.android.internal.os.ZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure, followed by boolean to
             * indicate whether a wrapper process was used.
             */
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();

            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

注释也说的很清楚,给Zygote发送一个argument list。通知Zygote进程启动一个子进程。再接下来就该和Zygote进程打交道了。

太晚了,关键明天还要上班。明天再细致分析这部分,古耐~

大哥大Zygote

在另一篇博文 Android Zygote启动流程源码解析中说到:在Zygote#main()中先注册了一个serverSocket,在启动了SystemServer进程之后,一直监听这个serverSocket,准备启动新的应用进程。大概过程如下:

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

ZygoteInit#main()

public static void main(String argv[]) {
    // 注册socket
    registerZygoteSocket(socketName);
    ...
    if (startSystemServer) {
        // 启动SystemServer进程
        startSystemServer(abiList, socketName);
    }
    // 监听socket,启动新的应用进程。--后文会讲
    runSelectLoop(abiList);
    closeServerSocket();
    ...
}

跟进runSelectLoop(abiList)

ZygoteInit#runSelectLoop()

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        while (true) {
            int index;
            ...
            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDescriptor());
            } else {
                boolean done;
                done = peers.get(index).runOnce();

                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }   
    }

    private static ZygoteConnection acceptCommandPeer(String abiList) {
        try {
            return new ZygoteConnection(sServerSocket.accept(), abiList);
        } catch (IOException ex) {
            ...
        }
    }

这个方法的主要作用是通过acceptCommandPeer()方法接收客户端发送的Socket消息。之后执行ZygoteConnection#runOnce()方法。跟进。

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

ZygoteConnection#runOnce()

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        ...
        checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
        checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
        ...
        if (pid == 0) {
            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                // should never get here, the child is expected to either
                // throw ZygoteInit.MethodAndArgsCaller or exec().
                return true;
            } else {
               ...
            }
            ...
    }

省略的一大段代码都在构造参数,之后根据参数调用Zygote.forkAndSpecialize()方法fork出应用程序进程,到这里,应用进程已经被创建了。因为是子进程pid = 0,所以之后会调用handleChildProc()方法进一步处理。跟进。

ZygoteConnection#handleChildProc()

    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
        closeSocket();
        ZygoteInit.closeServerSocket();
        ...
        ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
        ...
    }   

上述代码先关闭从Zygote进程继承来的ServerSocket,然后调用ZygoteInit.invokeStaticMain()。接下来的流程和启动System进程流程差不多,这里快速的过一遍。不熟悉这部分的同学可以参考这篇博客

源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

ZygoteInit#invokeStaticMain()

    static void invokeStaticMain(ClassLoader loader, String className, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
        try {
            cl = loader.loadClass(className);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className, ex);
        }
        Method m;
        m = cl.getMethod("main", new Class[] { String[].class });
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

意料之中的装载类文件、意料之中的反射、意料之中的验证修饰符、意料之中的抛出个异常,甚至意料之中的在Zygote#main()中捕获。看过Zygote启动流程源码解析的读着肯定和我有一样的感觉。接下来就该捕获异常,然后反射ActivityThread的静态方法main()。直接贴代码了,so boring…

ZygoteInit#main()

    public static void main(String argv[]) {
        try {
            ...
            runSelectLoop(abiList);
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        }

        // ZygoteInit&MethodAndArgsCaller#run()
        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                ...
            } 
        }

这里反射调用的是ActivityThread#main()方法。跟进。

主进程的创建流程

源码位置:frameworks/base/core/java/com/android/app/ActivityThread.java

ActivityThread#main()

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
        ...
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

我们知道ActivityThread就是所谓的主线程,其实ActivityThread并不是一个主线程。只是一个拥有mainLooper的入口方法。

概述中说:在Android系统中,启动四大组件中的任何一个都可以启动应用程序。启动四大组件的都可以启动应用程序,但实际上入口方法只有ActivityThread#main()一个(未验证)。

在做了一些初始化的工作后,调用了ActivityThread#attach(false)。跟进。

    final ApplicationThread mAppThread = new ApplicationThread();

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            ...
        }
        ...
    }

前文AMS中的Binder机制中分析过:ActivityManagerNative.getDefault(),返回的是AMS。其中跟进。

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#attachApplication()

    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

这里只是调用两个参数的attachApplicationLocked()方法处理。跟进。

    private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
        ...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        ...
    }

跟进。

源码位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

ActivityStackSupervisor#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 (!isFrontStack(stack)) {
                    continue;
                }
                ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            ...
                        }
                    }
                }
            }
        }
        ...
        return didSomething;
    }

首先遍历所有stack,之后找到目前被置于前台的stack。之后通过topRunningActivityLocked()获取最上面的Activity。最后调用realStartActivityLocked()方法来真正的启动目标Activity。跟进

源码位置:frameworks/base/services/java/com/android/server/am/ActivityStack.java

ActivityStack#realStartActivityLocked()

    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
        ...
                    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
                    r.icicle, r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);
    }
    ...

这里通过Binder,会调用ApplicationThread#scheduleLaunchActivity()。跟进。

源码位置:frameworks/base/core/java/android/app/ActivityThread.java

ActivityThread&ApplicationThread#scheduleLaunchActivity()

        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);
            ActivityClientRecord r = new ActivityClientRecord();
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            ...
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

构造一个ActivityClientRecord对象之后,调用sendMessage(H.LAUNCH_ACTIVITY, r)。跟进。

    private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

根据参数组装了一个Message对象,之后通过mH.sendMessage(msg)发送出去。看下mH是个什么鬼。跟进。

ActivityThread、ActivityThread&H

public final class ActivityThread {
    ...
    final H mH = new H();
    ...
        private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        ...
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ...
            }
        }
    }
}

原来mH不过是Handler的子类罢了。接着在handleMessage()中解析出Message对象,然后调用handleLaunchActivity()进一步处理。跟进。

ActivityThread#handleLaunchActivity()

    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
        ......  
        // 加载activity,然后调用onCreate,onStart方法
        Activity a = performLaunchActivity(r, customIntent);  
        if (a != null) {
            // 调用onResume方法
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            ...   
        }
        ... 
    }  

这是个蛮重要的方法。Activity启动流程源码解析里有详细讲解,这里暂时略过。
跟进。

ActivityThread#performLaunchActivity()

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        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 {
            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) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

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

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                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) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
    }

因为这个方法比较重要,所以代码完整的贴出来了。可以看到,首先收集要启动的Activity信息。然后通过ClassLoader加载目标Activiy类。再然后创建Application,最后调用Activity#onCreate()。内容有些多,我们一步步的看。先从创建Application说起。r.packageInfoLoadedApk对象,所以会调用LoadedApk#makeApplication()

源码位置:frameworks/base/core/java/android/app/LoadedApk.java

LoadedApk#makeApplication()

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;
        ...
        try {
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
        } catch (Exception e) {
            ...
        }
        ...
        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                ...
                }
            }
        }
        return app;
    }

方法名称已经很明显了。跟进。

源码位置:frameworks/base/core/java/android/app/Instrumentation.java

Instrumentation#newApplication()

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }

    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

简单粗暴,通过反射创建一个Application实例。现在实例有了,但onCreate()方法还没有被调用。跟进Instrumentation#callApplicationOnCreate()

    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

这都没法解析了,,直接调用Application#onCreate()。现在已经有了Application,但Activity只是被ClassLoader装载了,onCreate()还没有调起来。回到ActivityThread#performLaunchActivity()

        ...
        activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);

        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        ...

跟进。

源码位置:frameworks/base/core/java/android/app/callActivityOnCreate.java

Instrumentation#callActivityOnCreate()

    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }

    // Activity#performCreate()
    final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

Activity#performCreate()这里调用了OnCreate()方法。终于把我们的应用程序启动起来了~

总结

总体流程

  1. Launcher通过Binder机制通知AMS启动一个Activity
  2. AMS使Launcher栈最顶端Activity进入onPause状态
  3. AMS通知Process使用Socket和Zygote进程通信,请求创建一个新进程
  4. Zygote收到Socket请求,fork出一个进程,并调用ActivityThread#main()
  5. ActivityThread通过Binder通知AMS启动应用程序
  6. AMS通知ActivityStackSupervisor真正的启动Activity
  7. ActivityStackSupervisor通知ApplicationThread启动Activity
  8. ApplicationThread发消息给ActivityThread,需要启动一个Activity
  9. ActivityThread收到消息之后,通知LoadedApk创建Applicaition,并且调用其onCteate()方法
  10. ActivityThread装载目标Activity类,并调用Activity#attach()
  11. ActivityThread通知Instrumentation调用Activity#onCreate()
  12. Instrumentation调用Activity#performCreate(),在Activity#performCreate()中调用自身onCreate()方法

第一次启动应用程序,Application和Activity#onCreate()方法调用顺序

  1. 装载Activity
  2. 装载Application
  3. Application#attach()
  4. Application#onCreate()
  5. Activity#attach()
  6. Activity#onCreate()


更多Framework源码解析,请移步 Framework源码解析系列[目录]

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android LauncherAndroid系统上的一个应用程序,它是用户与系统交互的主要界面,也是用户启动应用程序的入口。它允许用户查看、操作和管理应用程序、小部件和系统功能。 Android Launcher源码解析涉及到多个关键组件和类。其中最重要的是LauncherActivity、PackageManager、AppWidgetManager和DesktopPane。 LauncherActivity是应用程序启动的入口点。它负责显示主屏幕和响应用户的触摸事件。在LauncherActivity中,使用了ViewPager来创建多个屏幕来容纳应用程序和小部件。 PackageManager是应用程序的管理器。通过PackageManager,Launcher可以获取系统中安装的应用程序信息、启动应用程序和监听应用程序的安装、卸载等事件。 AppWidgetManager用于管理应用程序的小部件。Launcher通过AppWidgetManager注册、更新和删除小部件。它还负责接收小部件的更新事件。 DesktopPane是主屏幕的容器。它使用GridLayout将应用程序和小部件布局在主屏幕上。DesktopPane还处理用户在主屏幕上的拖放操作,允许用户重新排序应用程序和小部件。 在源码解析过程中,还需要了解Android应用程序交互的一些核心概念,如Intent、Broadcast和Service等。Intent用于在组件之间传递消息,Broadcast用于传递系统事件,Service用于在后台执行任务。 在分析Launcher源码时,还需要关注性能优化和用户体验。例如,使用异步加载和缓存来提高应用程序和小部件的加载速度,使用动画效果来增强界面的流畅性。 综上所述,Android Launcher源码解析涉及多个组件和类,需要了解Android应用程序交互的核心概念,同时需要关注性能优化和用户体验。这个过程可以帮助开发者深入理解和定制Android系统的启动器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值