关于android:App启动流程源码分析

5次阅读

共计 27472 个字符,预计需要花费 69 分钟才能阅读完成。

前言

== 本次次要内容包含:==

1、App 的启动源码剖析

2、启动过程要害节点

一、App 启动源码流程剖析

App 启动流程的入口是通过 Launcher 的 startActivity,通过手机桌面图标点击跳转,如下类:

\frameworks\base\core\java\android\app\LauncherActivity.java

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

startActivity 是如何实现的?

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

该类最终执行到 Instrumentation 的 execStartActivity 办法,查看正文剖析如下:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {
    //1、首先执行该办法    
    @Override
    public void startActivity(Intent intent) {this.startActivity(intent, null);
    }
    //2、跳转至该办法
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            //3、最终判断执行该办法,持续剖析 startActivityForResult
            startActivityForResult(intent, -1);
        }
    }
    //4、跳转至该办法
    public void startActivityForResult(Intent intent, int requestCode) {startActivityForResult(intent, requestCode, null);
    }
    //5、跳转至此,该办法有点长,只剖析重点
    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {if (mParent == null) {
            //6、执行这里 execStartActivity,持续看 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) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {if (options != null) {mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }
}

剖析:

1、mInstrumentation 的成员变量调用了它的 execStartActivity 办法

2、这里还看到有一个 mMainThread 的变量,猜想是 APP 的主线程

3、这两个变量在哪里实例化的呢?持续查看 Activity.java 有如下办法:

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
        // 执行该办法    
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();
        //1、mMainThread 变量的定义
        mMainThread = aThread;
        //2、mInstrumentation 变量的定义
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {if (lastNonConfigurationInstances != null) {mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;} else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

剖析:

1、如上,这几个变量是传进来的,然而在 Activity 中没有任何中央调用到这段代码

2、猜想,它的实例化肯定是在别的类中实现的。

3、这里收住,按既定的流程走,不然很容易绕进去,这里的确我绕进去出不来过。

== 持续剖析如上 Activity.java 类最终执行到 Instrumentation 的 execStartActivity 办法 ==

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

public class Instrumentation {

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        //1、看重点,这里又呈现了 startActivity 调用者 ActivityManagerNative.getDefault() 是什么呢?//2、通过源码剖析 getDefault 的定义会发现 getDefault 办法返回的是一个 IActivityManager 类型的对象
        //3、IActivityManager 是一个接口,实在返回的其实是一个 ActivityManagerService
        //4、该类继承自 ActivityManagerNative,而 ActivityManagerNative 则实现了 IActivityManager 接口
        //5、同时还继承了 Binder , 很显然 ActivityManagerService 是一个 Binder 对象
        try {intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            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;
    }
}

1、看重点,这里又呈现了 startActivity 调用者 ActivityManagerNative.getDefault() 是什么呢?

2、通过源码剖析 getDefault 的定义会发现 getDefault 办法返回的是一个 IActivityManager 类型的对象

3、IActivityManager 是一个接口,实在返回的其实是一个 ActivityManagerService

4、该类继承自 ActivityManagerNative,而 ActivityManagerNative 则实现了 IActivityManager 接口

5、同时还继承了 Binder , 很显然 ActivityManagerService 是一个 Binder 对象

6、综上剖析,咱们进入 ActivityManagerService 的 startActivity 办法。

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

进入该办法之后又会调用该类的 startActivityAsUser 办法。

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

    @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) {enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }
}

1、正文:Switch to user app stacks here. 要切换到用户的 APP 栈。

2、接着返回执行了 ActivityStackSupervisor 的 startActivityMayWait 这个办法。

3、startActivityMayWait 这外面还会接着调用到 startActivityLocked 办法,该办法是 ActivityStack.java 中的办法:

\frameworks\base\services\core\java\com\android\server\am\ActivityStack.java

final class ActivityStack {
    
    final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
            
        // 省略...
        
        if (!isHomeStack() || numActivities() > 0) {
            //1、留神:这里有个开始启动前启动了一个预览的 window
            // We want to show the starting preview window if we are
            // switching to a new task, or the next activity's process is
            // not currently running.
            boolean showStartingIcon = newTask;
            ProcessRecord proc = r.app;
            if (proc == null) {proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
            }
            if (proc == null || proc.thread == null) {showStartingIcon = true;}
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting" + r);
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
                mNoAnimActivities.add(r);
            } else {
                mWindowManager.prepareAppTransition(newTask
                        ? r.mLaunchTaskBehind
                                ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
                                : AppTransition.TRANSIT_TASK_OPEN
                        : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                mNoAnimActivities.remove(r);
            }
            mWindowManager.addAppToken(task.mActivities.indexOf(r),
                    r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
            boolean doShow = true;
            
            // 省略...
            
            if (r.mLaunchTaskBehind) {
                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
                // tell WindowManager that r is visible even though it is at the back of the stack.
                mWindowManager.setAppVisibility(r.appToken, true);
                ensureActivitiesVisibleLocked(null, 0);
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                // Figure out if we are transitioning from another activity that is
                // "has the same starting icon" as the next one.  This allows the
                // window manager to keep the previous window it had previously
                // created, if it still had one.
                ActivityRecord prev = mResumedActivity;
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
                    if (prev.task != r.task) {prev = null;}
                    // (2) The current activity is already displayed.
                    else if (prev.nowVisible) {prev = null;}
                }
                //2、mWindowManager.setAppStartingWindow();
                mWindowManager.setAppStartingWindow(
                        r.appToken, r.packageName, r.theme,
                        mService.compatibilityInfoForPackageLocked(r.info.applicationInfo), r.nonLocalizedLabel,
                        r.labelRes, r.icon, r.logo, r.windowFlags,
                        prev != null ? prev.appToken : null, showStartingIcon);
                r.mStartingWindowShown = true;
            }
        } else {
            // If this is the first activity, don't do any fancy animations,
            // because there is nothing for it to animate on top of.
            mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                    r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
            ActivityOptions.abort(options);
            options = null;
        }
        if (VALIDATE_TOKENS) {validateAppTokensLocked();
        }
        // 代码又从 ActivityStack 回到了 mStackSupervisor 中
        if (doResume) {mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

}

剖析:

1、执行前这里想要开始启动前启动一个预览的 window

2、通过 mWindowManager.setAppStartingWindow();

3、WindowManagerService 执行了 addStartingWindow();

4、展现 Starting Window

== 接着持续走启动流程业务:==

1、在办法最初,代码又从 ActivityStack 回到了 mStackSupervisor 中,

2、在 resumeTopActivitiesLocked 中,首先判断了以后栈是否是 Top 栈,如果没有问题,就回到 ActivityStack 中,

3、resumeTopActivityLocked() 又调用了 resumeTopActivityInnerLocked(),这个办法里重点就来了:

4、resumeTopActivityInnerLocked() 这里间接看到外面有一句是通过 ActivityStackSupervisor 去调用的

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

== 新过程的创立:==

这个 startSpecificActivityLocked() 进行了一波过程是否存在的判断,接着会调用 ActivityManagerService 的 startProcessLocked() 开始过程的创立

public final class ActivityStackSupervisor implements DisplayListener {
    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.
        }
        //APP 还未创立才会走到这里,通过 ActivityManagerService 开启过程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
}

ActivityManagerService 的 startProcessLocked() 这个过程创立的过程也凹凸起伏的:

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

    // Start the process.  It will either succeed and return a result containing
    // the PID of the new process, or else throw a RuntimeException.
    boolean isActivityProcess = (entryPoint == null);
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc:" +
            app.processName);
    checkTime(startTime, "startProcess: asking zygote to start proc");
    //Process.start() 实现了 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);
    checkTime(startTime, "startProcess: returned from zygote!");
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

Process.start() 实现了 ActivityThread 的创立,之后就会执行 ActivityThread 的 main() 办法

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

1、在 Process.start 办法中,理论调用的是 startViaZygote 办法

2、在这个办法里通过 openZygoteSocketIfNeeded 关上 Zygote 的 socket,并通过 zygoteSendArgsAndGetResult 进行交互。

3、接着持续往下就会通过 JNI 调用到零碎底层的内核代码了。

4、其实在 Android 外面的每一个 App 过程都是通过 Zygote 过程 fork 进去的。

5、而且 Zygote 是属于零碎过程来的,所以这里须要建设 socket 与其进行交互,为 App 启动创立新的过程。

6、新的过程创立了将会进入 ActivityThread 的 main 办法,代码如下:

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

public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        AndroidKeyStoreProvider.install();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");
        
        //1、Looper 终于在此闪亮退场
        Looper.prepareMainLooper();
        
        //2、thread.attach(false); 办法执行
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

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

        if (false) {Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    
    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {//mgr 是 IActivityManager,也就是说这里通过 AIDL 调用了 ActivityManagerService 的 attachApplication(mAppThread)
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {// Ignore}
    }

剖析 main 函数整体流程:

1、首先调用 Looper.prepareMainLooper 去创立一个主线程的 Looper

2、这个主线程的 Looper 是很重要的,零碎对于 App 的很多治理都须要通过这个 Looper 去将消息传递到 ActivityThread 的 Handler 外面去执行。

3、这外面当然包含了 Acticity 的工作流程。

4、接着,为整个利用创立了一个 ActivityThread 对象。

5、attach 办法之后,通过 thread.getHandler 办法去获取到主线程的 Handler,

6、而后就调用 Looper.loop() 让主线程的 Looper 进入轮询状态,期待音讯过去解决。至此 UI 线程启动结束。

剖析 attach 流程:

1、调用这个 attach 的时候传入的是 false

2、所以执行会通过 ActivityManagerService 调用到 attachApplication;

3、外面会调用 attachApplicationLocked,

4、而后就是在这个办法外面,又通过 ApplicationThread 调用了 bindApplication

代码如下:

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

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

public final void bindApplication(String processName, ApplicationInfo appInfo,
        List<ProviderInfo> providers, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation,
        boolean isRestrictedBackupMode, boolean persistent, Configuration config,
        CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {if (services != null) {
        // Setup the service cache in the ServiceManager
        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);
}

bindApplication 剖析:

1、数据传递封装通过一个叫 AppBindData 的形式包装起来,

2、而后通过 Handler 形式,发送给了一个叫 H 的 Handler 实例,

3、这个实例在 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.
        //1、这里 makeApplication
        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) {...}
        //2、Application 的 onCreate() 执行
        try {mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {...}
    } finally {StrictMode.setThreadPolicy(savedPolicy);
    }
}

1、在 handleBindApplication 这个办法外面,为这个利用创立了惟一的 Application 对象,和惟一的 Instrumentation 对象

2、Application app = data.info.makeApplication(data.restrictedBackupMode, null); 这里最终调用了 Application 的 attachBaseContext(context);

3、mInstrumentation.callApplicationOnCreate(app); 的调用执行了 Application 的 onCreate 办法。到这里,Application 创立了。

Application 中在 onCreate() 办法里去初始化各种全局的变量数据是举荐的做法,然而如果你想把初始化的工夫点提前到极致,也能够去重写 attachBaseContext() 办法

public class CustomApplication extends Application {  

    @Override  
    protected void attachBaseContext(Context base) {  
        // 在这里调用 Context 的办法会解体  
        super.attachBaseContext(base);  
        // 在这里能够失常调用 Context 的办法  
    }  

}

持续剖析:

1、前面通过 ActivityStackSupervisor 调用 attachApplicationLocked, 并且传入了一个 ProcessRecord 对象。

2、外面会调用 realStartActivityLocked 这个办法

3、而后这个办法外面又会通过 ApplicationThread 调用 scheduleLaunchActivity。

4、大抵过程和下面创立 Application 的时候流程始终,最终还是会调用到 scheduleLaunchActivity 的真正实现

5、完后,这个办法外面最好会发送一条音讯到 H 外面去解决:sendMessage(H.LAUNCH_ACTIVITY, r)。

LAUNCH_ACTIVITY 接管如下分支:

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);
    //1、调用 handleLaunchActivity() 办法
    handleLaunchActivity(r, null);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    if (r.profilerInfo != null) {mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();}

    // Make sure we are running with the most recent config.
    handleConfigurationChanged(null, null);

    if (localLOGV) Slog.v(TAG, "Handling launch of" + r);

    // Initialize before creating the activity
    WindowManagerGlobal.initialize();
    //2、Activity 终于被创立了, 调用了 performLaunchActivity 办法创立 Activity
    Activity a = performLaunchActivity(r, customIntent);

    // 如果 Activity 被创立胜利的话,会调用 handleResumeActivity 
    // 而后会调用到 performResumeActivity,// 而后会调用到 Activity 的 performResume 办法
    // 最终调用到 activity.onResume() 生命周期办法
    if (a != null) {r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);

        if (!r.activity.mFinished && r.startsNotResumed) {
            // The activity manager actually wants this one to start out
            // paused, because it needs to be visible but isn't in the
            // foreground.  We accomplish this by going through the
            // normal startup (because activities expect to go through
            // onResume() the first time they run, before their window
            // is displayed), and then pausing it.  However, in this case
            // we do -not- need to do the full pause cycle (of freezing
            // and such) because the activity manager assumes it can just
            // retain the current state it has.
            try {
                r.activity.mCalled = false;
                mInstrumentation.callActivityOnPause(r.activity);
                // We need to keep around the original state, in case
                // we need to be created again.  But we only do this
                // for pre-Honeycomb apps, which always save their state
                // when pausing, so we can not have them save their state
                // when restarting from a paused state.  For HC and later,
                // we want to (and can) let the state be saved as the normal
                // part of stopping the activity.
                if (r.isPreHoneycomb()) {r.state = oldState;}
                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) {if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
                            "Unable to pause activity"
                            + r.intent.getComponent().toShortString()
                            + ":" + e.toString(), e);
                }
            }
            r.paused = true;
        }
    } else {
        // If there was an error, for any reason, tell the activity
        // manager to stop us.
        try {ActivityManagerNative.getDefault()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
        } catch (RemoteException ex) {// Ignore}
    }
}

接着看一下 performLaunchActivity 做了什么?

外面调用了 Activity 的 onCreate 和 onStart 等生命周期办法,包含 Theme 等的设置

    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();
            //1、mInstrumentation 通过 newActivity 调用了 ActivityActivity 的 onCreate 和 onStart 等生命周期办法
            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;
                //Activity 的 Theme 主题的设置
                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;
    }

Application 以及 Activity 的启动流程图如下:


关注我的技术公众号

正文完
 0