Android源码分析之App启动流程(二)

续前节,我们已经知道,Zygote孵化完进程之后会invoke ActivityThread#main方法,现在继续看剩下的部分。该方法代码如下:

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

public static void main(String[] args) {
    ...

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

可以看到这里首先开启了Looper消息循环,这部分知识我们以后再来分析。下面主要看下ActivityThread#attach(boolean)方法,代码如下:

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        ...
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        ...
    } else {
        ...
    }

    ...
}

因为不是系统APP,所以只需要看if里的代码就好了。之前已经分析过,ActivityManagerNative#getDefault()方法获取到的是ActivityManagerProxy实例,然后这个实例通过BinderProxyActivityManagerService进行通信。接下来代码如下:

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

public void attachApplication(IApplicationThread app) throws RemoteException
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(app.asBinder());
    mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
    reply.readException();
    data.recycle();
    reply.recycle();
}

和之前的做法非常一致,接下来会执行到ActivityManagerService#onTransact方法,而相关代码在父类ActivityManagerNative中,代码如下:

case ATTACH_APPLICATION_TRANSACTION: {
    data.enforceInterface(IActivityManager.descriptor);
    IApplicationThread app = ApplicationThreadNative.asInterface(
            data.readStrongBinder());
    if (app != null) {
        attachApplication(app);
    }
    reply.writeNoException();
    return true;
}

这里看到IApplicationThread实例是通过ApplicationThreadNative#asInterface获取的,根据先前的经验,这里应该是一个ApplicationThreadProxy实例,相关代码如下:

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

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

    return new ApplicationThreadProxy(obj);
}

接下来就可以确认,ActivityManagerService#attachApplication(IApplicationThread)方法中的IApplicationThread实例是ApplicationThreadProxy,代码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

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

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {
    ...
    try {
        ...
        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked());
        updateLruProcessLocked(app, false, null);
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
    } catch (Exception e) {
        ...
    }

    ...
    
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    ...
    return true;
}

然后看下这里ApplicationThreadProxy#bindApplication方法,代码如下:

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

public final void bindApplication(String packageName, ApplicationInfo info,
        List providers, ComponentName testName, ProfilerInfo profilerInfo,
        Bundle testArgs, IInstrumentationWatcher testWatcher,
        IUiAutomationConnection uiAutomationConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode,
        boolean persistent, Configuration config, CompatibilityInfo compatInfo,
        Map services, Bundle coreSettings) throws RemoteException {
    ...
    mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
            IBinder.FLAG_ONEWAY);
    data.recycle();
}

这里的思路和ActivityManagerNative十分一致,通过ApplicationThreadProxyBinderProxy来完成ApplicationThreadActivityManagerService通信,然后由ApplicationThreadNative处理返回的结果,并调用ApplicationThread的对应方法。接下来看下ApplicationThread#bindApplication方法:

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

public final void bindApplication(String processName, ApplicationInfo appInfo,
        List providers, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation,
        boolean isRestrictedBackupMode, boolean persistent, Configuration config,
        CompatibilityInfo compatInfo, Map services, Bundle coreSettings) {

    if (services != null) {
        // Setup the service cache in the ServiceManager
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);

    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.instrumentationUiAutomationConnection = instrumentationUiConnection;
    data.debugMode = debugMode;
    data.enableBinderTracking = enableBinderTracking;
    data.trackAllocation = trackAllocation;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    sendMessage(H.BIND_APPLICATION, data);
}

这里把一些需要设置的属性,通过一个叫AppBindData的方式包装起来,然后通过Handler方式,发送给了一个叫HHandler实例,这个实例在ActivityThread中,我们看下它在handleMessage中对BIND_APPLICATION这个消息的处理:

case BIND_APPLICATION:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
    AppBindData data = (AppBindData)msg.obj;
    handleBindApplication(data);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;

private void handleBindApplication(AppBindData data) {
    ...
    // Continue loading instrumentation.
    if (ii != null) {
        ...
        mInstrumentation.init(this, instrContext, appContext, component,
                data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

        if (mProfiler.profileFile != null && !ii.handleProfiling
                && mProfiler.profileFd == null) {
            mProfiler.handlingProfiling = true;
            final File file = new File(mProfiler.profileFile);
            file.getParentFile().mkdirs();
            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
        }
    } else {
        mInstrumentation = new Instrumentation();
    }

    ...

    try {
        // If the app is being launched for full backup or restore, bring it up in
        // a restricted environment with the base application class.
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        ...

        // Do this after providers, since instrumentation tests generally start their
        // test thread at this point, and we don't want that racing.
        try {
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
            ...
        }

        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

handleBindApplication做了非常多的工作,APP的名称、资源、屏幕相关等操作都在这里进行了处理,但这不是我们今天关注的重点,我们主要看最下边的try-catch,这里首先创建了一个Application实例,然后调用了mInstrumentation.onCreatemInstrumentation.callApplicationOnCreate,这两个方法一个是空的,一个调用了Application#onCreate(),没有做更多的事情,这里暂时不关注它。这里这个Application实例是通过LoadedApk#makeApplication完成的,代码如下:

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

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

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    }

    ...
    return app;
}

可以看到这个Application是通过Instrumentation#newApplication方法完成的,代码如下:

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

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是通过ClassLoader创建出来的,随后调用了它的attach方法,该方法如下:

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

/* package */ final void attach(Context context) {
    attachBaseContext(context);
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

至此,Application就创建完毕了,并且Application#onCreate()方法也执行完毕了。接下来就是启动Activity的过程,在之前分析ActivityManagerService#attachApplicationLocked方法中,执行完毕thread.bindApplication之后又执行了mStackSupervisor.attachApplicationLocked(app),也就是创建完Application之后,启动需要运行的Activity,相应的代码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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

因为是首次运行,所以会执行到if (realStartActivityLocked(hr, app, true, true))代码块,如下所示:

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

        ...
    } catch (RemoteException e) {
        ...
    }
    ...
    return true;
}

现在,终于开始加载Activity了,代码如下:

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

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 pendingResults, List pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();

    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

可以看到这里依然是通过H来交互的,代码如下:

case LAUNCH_ACTIVITY: {
    ...
    
    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...

    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
    } else {
        ...
    }
}

这里首先通过performLaunchActivity获取到需要加载的Activity,然后调用handleResumeActivity方法。我们先看前者,代码如下:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        ...
    }

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

        if (activity != null) {
            Context appContext = createBaseContextForActivity(r, activity);
            ...
            
            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, window);
            ...
            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 (!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);
                }
                ...
            }
        }
        r.paused = true;

        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        ...
    }

    return activity;
}

这里首先通过Instrumentation#newActivity方法创建了一个Activity,然后调用了它的一些生命周期方法,包括它的ThemeWindow等都是在这时候设置的,还是先看下创建的过程,代码如下:

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

和创建Application一样,也是通过ClassLoader完成的,Activity创建完成后接着调用了Activity#attach方法,在最开始时候提到过这个方法,并说它需要的ActivityThread是通过这个方法传入的,这里终于找到调用的地方了。接下来依次调用了ActivityonCreateonStartonRestoreInstanceStateonPostCreate方法,最后回到handleLaunchActivity,调用了handleResumeActivity。接下来的代码就涉及到了Activity加载View了,我们之后再分析。

上一篇:Android源码分析之App启动流程(一)

下一篇:Android源码分析之Activity启动与View绘制流程

你可能感兴趣的:(Android源码分析之App启动流程(二))