天天看點

Activity啟動流程Activity啟動流程及生命周期

Activity啟動流程及生命周期

1、概述

在上一篇http://blog.csdn.net/starlight_2012/article/details/78116916 Handler、Looper、MessageQueue源碼分析我們知道在ActivityThread中Looper.looper()以後就會輪詢MessageQueue隊列,那麼Activity是如何啟動的?本篇将帶你解析Activity的啟動流程。本章篇幅比較大,請耐心品讀。

2、Activity啟動原理分析

我們繼續看ActivityThread中Looper.Loop()前系統把我們做了什麼操作?

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

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

            Looper.prepareMainLooper();

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

我們發現在系統中調用了thread.attach(false)方法,我們知道目前類在ActivityThread中,檢視下thread.attach(false)方法

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

                //擷取ActivityManagerService
                final IActivityManager mgr = ActivityManagerNative.getDefault();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
                // Watch for getting close to heap limit.
                BinderInternal.addGcWatcher(new Runnable() {
                    @Override public void run() {
                        if (!mSomeActivitiesChanged) {
                            return;
                        }
                        Runtime runtime = Runtime.getRuntime();
                        long dalvikMax = runtime.maxMemory();
                        long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                        if (dalvikUsed > ((3*dalvikMax)/4)) {
                            if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                    + " total=" + (runtime.totalMemory()/1024)
                                    + " used=" + (dalvikUsed/1024));
                            mSomeActivitiesChanged = false;
                            try {
                                mgr.releaseSomeActivities(mAppThread);
                            } catch (RemoteException e) {
                                throw e.rethrowFromSystemServer();
                            }
                        }
                    }
                });
            } else {
                // Don't set application object here -- if the system crashes,
                // we can't display an alert, we just want to die die die.
                android.ddm.DdmHandleAppName.setAppName("system_process",
                        UserHandle.myUserId());
                try {
                    mInstrumentation = new Instrumentation();
                    ContextImpl context = ContextImpl.createAppContext(
                            this, getSystemContext().mPackageInfo);
                    mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                    mInitialApplication.onCreate();
                } catch (Exception e) {
                    throw new RuntimeException(
                            "Unable to instantiate Application():" + e.toString(), e);
                }
            }

            // add dropbox logging to libcore
            DropBox.setReporter(new DropBoxReporter());

            ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    synchronized (mResourcesManager) {
                        // We need to apply this change to the resources
                        // immediately, because upon returning the view
                        // hierarchy will be informed about it.
                        if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                            updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                                    mResourcesManager.getConfiguration().getLocales());

                            // This actually changed the resources!  Tell
                            // everyone about it.
                            if (mPendingConfiguration == null ||
                                    mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                                mPendingConfiguration = newConfig;

                                sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                            }
                        }
                    }
                }
                @Override
                public void onLowMemory() {
                }
                @Override
                public void onTrimMemory(int level) {
                }
    });
           

由于我們傳遞的system為false表示不是系統app,所有進入if語句中,調用ViewRootImpl.addFirstDrawHandler方法(後面會講述ViewRootImpl類,很重要的類後面講述View的繪制和螢幕觸摸等事件分發)後,調用IActivityManager mgr = ActivityManagerNative.getDefault();擷取ActivityManagerService,可以看到最後調用的是通過ServiceManager.getService(“activity”);擷取ActivityManagerService服務是通過Binder遠端擷取的

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

     private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
                IBinder b =ServiceManager.getService("activity");
                if (false) {
                    Log.v("ActivityManager", "default service binder = " + b);
                }
                IActivityManager am = asInterface(b);
                if (false) {
                    Log.v("ActivityManager", "default service = " + am);
                }
                return am;
            }
    };
           

調用ActivityManagerService服務中的attachApplication方法,mgr.attachApplication(mAppThread);

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

在attachApplication中調用 attachApplicationLocked(thread, callingPid)方法

private final boolean attachApplicationLocked(IApplicationThread ;thread,
        int pid) {

            // Find the application record that is being attached...  either via
            // the pid if we are running in multiple processes, or just pull the
            // next app record if we are emulating process with anonymous threads.
            ProcessRecord app;
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    app = mPidsSelfLocked.get(pid);
                }
            } else {
                app = null;
            }

            if (app == null) {
                Slog.w(TAG, "No pending application record for pid " + pid
                        + " (IApplicationThread " + thread + "); dropping process");
                EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
                if (pid > 0 && pid != MY_PID) {
                    Process.killProcessQuiet(pid);
                    //TODO: killProcessGroup(app.info.uid, pid);
                } else {
                    try {
                        thread.scheduleExit();
                    } catch (Exception e) {
                        // Ignore exceptions.
                    }
                }
                return false;
            }

            // If this application record is still attached to a previous
            // process, clean it up now.
            if (app.thread != null) {
                handleAppDiedLocked(app, true, true);
            }

            // Tell the process all about itself.

            if (DEBUG_ALL) Slog.v(
                    TAG, "Binding process pid " + pid + " to record " + app);

            final String processName = app.processName;
            try {
                AppDeathRecipient adr = new AppDeathRecipient(
                        app, pid, thread);
                thread.asBinder().linkToDeath(adr, 0);
                app.deathRecipient = adr;
            } catch (RemoteException e) {
                app.resetPackageList(mProcessStats);
                startProcessLocked(app, "link fail", processName);
                return false;
            }

            EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

            app.makeActive(thread, mProcessStats);
            app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
            app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            app.forcingToForeground = null;
            updateProcessForegroundLocked(app, false, false);
            app.hasShownUi = false;
            app.debugging = false;
            app.cached = false;
            app.killedByAm = false;
            app.killed = false;


            // We carefully use the same state that PackageManager uses for
            // filtering, since we use this flag to decide if we need to install
            // providers when user is unlocked later
            app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);

            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

            boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
            List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;

            if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
                Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
            }

            if (!normalMode) {
                Slog.i(TAG, "Launching preboot mode app: " + app);
            }

            if (DEBUG_ALL) Slog.v(
                TAG, "New app record " + app
                + " thread=" + thread.asBinder() + " pid=" + pid);
            try {
                int testMode = IApplicationThread.DEBUG_OFF;
                if (mDebugApp != null && mDebugApp.equals(processName)) {
                    testMode = mWaitForDebugger
                        ? IApplicationThread.DEBUG_WAIT
                        : IApplicationThread.DEBUG_ON;
                    app.debugging = true;
                    if (mDebugTransient) {
                        mDebugApp = mOrigDebugApp;
                        mWaitForDebugger = mOrigWaitForDebugger;
                    }
                }
                String profileFile = app.instrumentationProfileFile;
                ParcelFileDescriptor profileFd = null;
                int samplingInterval = 0;
                boolean profileAutoStop = false;
                if (mProfileApp != null && mProfileApp.equals(processName)) {
                    mProfileProc = app;
                    profileFile = mProfileFile;
                    profileFd = mProfileFd;
                    samplingInterval = mSamplingInterval;
                    profileAutoStop = mAutoStopProfiler;
                }
                boolean enableTrackAllocation = false;
                if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
                    enableTrackAllocation = true;
                    mTrackAllocationApp = null;
                }

                // If the app is being launched for restore or full backup, set it up specially
                boolean isRestrictedBackupMode = false;
                if (mBackupTarget != null && mBackupAppName.equals(processName)) {
                    isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
                            && ((mBackupTarget.backupMode == BackupRecord.RESTORE)
                                    || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
                                    || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
                }

                if (app.instrumentationClass != null) {
                    notifyPackageUse(app.instrumentationClass.getPackageName(),
                                     PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
                        + processName + " with config " + mConfiguration);
                ApplicationInfo appInfo = app.instrumentationInfo != null
                        ? app.instrumentationInfo : app.info;
                app.compat = compatibilityInfoForPackageLocked(appInfo);
                if (profileFd != null) {
                    profileFd = profileFd.dup();
                }
                ProfilerInfo profilerInfo = profileFile == null ? null
                        : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
                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) {
                // todo: Yikes!  What should we do?  For now we will try to
                // start another process, but that could easily get us in
                // an infinite loop of restarting processes...
                Slog.wtf(TAG, "Exception thrown during bind of " + app, e);

                app.resetPackageList(mProcessStats);
                app.unlinkDeathRecipient();
                startProcessLocked(app, "bind fail", processName);
                return false;
            }

            // Remove this record from the list of starting applications.
            mPersistentStartingProcesses.remove(app);
            if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                    "Attach application locked removing on hold: " + app);
            mProcessesOnHold.remove(app);

            boolean badApp = false;
            boolean didSomething = false;

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

            // Find any services that should be running in this process...
            if (!badApp) {
                try {
                    didSomething |= mServices.attachApplicationLocked(app, processName);
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                    badApp = true;
                }
            }

            // Check if a next-broadcast receiver is in this process...
            if (!badApp && isPendingBroadcastProcessLocked(pid)) {
                try {
                    didSomething |= sendPendingBroadcastsLocked(app);
                } catch (Exception e) {
                    // If the app died trying to launch the receiver we declare it 'bad'
                    Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                    badApp = true;
                }
            }

            // Check whether the next backup agent is in this process...
            if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
                if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
                        "New app is backup target, launching agent for " + app);
                notifyPackageUse(mBackupTarget.appInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
                try {
                    thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
                            compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
                            mBackupTarget.backupMode);
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
                    badApp = true;
                }
            }

            if (badApp) {
                app.kill("error during init", true);
                handleAppDiedLocked(app, false, true);
                return false;
            }

            if (!didSomething) {
                updateOomAdjLocked();
            }

            return true;
    }
           

通過mPidsSelfLocked中擷取目前程序記錄,目前App應用程式程序是通過zygote程序孵化的子程序,儲存在mPidsSelfLocked集合中,如果在程序集合中找不到目前應用程式就退出目前程式(注意此時查找程序操作是在ActivityManagerService程序和應用程式程序在不同的程序空間中)

ProcessRecord app;
                if (pid != MY_PID && pid >= 0) {
                       synchronized (mPidsSelfLocked) {
                       app = mPidsSelfLocked.get(pid);
                       }
                   } else {
                       app = null;
                   }

            if (app == null) {
                Slog.w(TAG, "No pending application record for pid " + pid
                        + " (IApplicationThread " + thread + "); dropping process");
                EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
                if (pid > 0 && pid != MY_PID) {
                    Process.killProcessQuiet(pid);
                    //TODO: killProcessGroup(app.info.uid, pid);
                } else {
                    try {
                        thread.scheduleExit();
                    } catch (Exception e) {
                        // Ignore exceptions.
                    }
                }
                return false;
            }
           

如果程序記錄中儲存以前程序中的線程時,就清空以前程序記錄

if (app.thread != null) {
        handleAppDiedLocked(app, true, true);
    }
           

normalMode=mProcessesReady || isAllowedWhileBooting(app.info),mProcessesReady的值為true(在ActivityManagerService.systemReady中指派),true||任何值都為true,接着調用IApplicationThread.bindApplication方法将ApplicationThread對象和ActivityManagerService綁定,IApplicationThread是遠端調用的接口(aidl),在ActivityThread中實作Binder接口

private class kApplicationThread extends ApplicationThreadNative {

              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方法發送一個消息sendMessage(H.BIND_APPLICATION, data)

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

    private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
        if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                        "seq= " + seq);
        Message msg = Message.obtain();
        msg.what = what;
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = obj;
        args.argi1 = arg1;
        args.argi2 = arg2;
        args.argi3 = seq;
        msg.obj = args;
        mH.sendMessage(msg);
    }
           

mH是ActivityThread中建立的一個Handler分發類,

private class H extends Handler {
            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, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                 } break;
               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;
               ...
      }
           

可以看到在Handler中調用ActivityThread中的handleBindApplication方法

private void handleBindApplication(AppBindData data) {
         // Register the UI Thread as a sensitive thread to the runtime.
         VMRuntime.registerSensitiveThread();
         if (data.trackAllocation) {
                DdmVmInternal.enableRecentAllocations(true);
         }

         // Note when this process has started.
        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());

        mBoundApplication = data;
        mConfiguration = new Configuration(data.config);
        mCompatConfiguration = new Configuration(data.config);

        mProfiler = new Profiler();
        if (data.initProfilerInfo != null) {
            mProfiler.profileFile = data.initProfilerInfo.profileFile;
            mProfiler.profileFd = data.initProfilerInfo.profileFd;
            mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
            mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
        }

        // send up app name; do this *before* waiting for debugger
        Process.setArgV0(data.processName);
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());

        if (data.persistent) {
            // Persistent processes on low-memory devices do not get to
            // use hardware accelerated drawing, since this can add too much
            // overhead to the process.
            if (!ActivityManager.isHighEndGfx()) {
                ThreadedRenderer.disable(false);
            }
        }

        if (mProfiler.profileFd != null) {
            mProfiler.startProfiling();
        }

        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
        // implementation to use the pool executor.  Normally, we use the
        // serialized executor as the default. This has to happen in the
        // main thread so the main looper is set right.
        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

        Message.updateCheckRecycle(data.appInfo.targetSdkVersion);

        /*
         * Before spawning a new process, reset the time zone to be the system time zone.
         * This needs to be done because the system time zone could have changed after the
         * the spawning of this process. Without doing this this process would have the incorrect
         * system time zone.
         */
        TimeZone.setDefault(null);

        /*
         * Set the LocaleList. This may change once we create the App Context.
         */
        LocaleList.setDefault(data.config.getLocales());

        synchronized (mResourcesManager) {
            /*
             * Update the system configuration since its preloaded and might not
             * reflect configuration changes. The configuration object passed
             * in AppBindData can be safely assumed to be up to date
             */
            mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
            mCurDefaultDisplayDpi = data.config.densityDpi;

            // This calls mResourcesManager so keep it within the synchronized block.
            applyCompatConfiguration(mCurDefaultDisplayDpi);
        }

        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

        /**
         * Switch this process to density compatibility mode if needed.
         */
        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
                == 0) {
            mDensityCompatMode = true;
            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
        }
        updateDefaultDensity();

        final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
        Boolean is24Hr = null;
        if (use24HourSetting != null) {
            is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
        }
        // null : use locale default for 12/24 hour formatting,
        // false : use 12 hour format,
        // true : use 24 hour format.
        DateFormat.set24HourTimePref(is24Hr);

        View.mDebugViewAttributes =
                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;

        /**
         * For system applications on userdebug/eng builds, log stack
         * traces of disk and network access to dropbox for analysis.
         */
        if ((data.appInfo.flags &
             (ApplicationInfo.FLAG_SYSTEM |
              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
            StrictMode.conditionallyEnableDebugLogging();
        }

        /**
         * For apps targetting Honeycomb or later, we don't allow network usage
         * on the main event loop / UI thread. This is what ultimately throws
         * {@link NetworkOnMainThreadException}.
         */
        if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
            StrictMode.enableDeathOnNetwork();
        }

        /**
         * For apps targetting N or later, we don't allow file:// Uri exposure.
         * This is what ultimately throws {@link FileUriExposedException}.
         */
        if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
            StrictMode.enableDeathOnFileUriExposure();
        }

        NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted(
                (data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0);

        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
            // XXX should have option to change the port.
            Debug.changeDebugPort(8100);
            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
                Slog.w(TAG, "Application " + data.info.getPackageName()
                      + " is waiting for the debugger on port 8100...");

                IActivityManager mgr = ActivityManagerNative.getDefault();
                try {
                    mgr.showWaitingForDebugger(mAppThread, true);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }

                Debug.waitForDebugger();

                try {
                    mgr.showWaitingForDebugger(mAppThread, false);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }

            } else {
                Slog.w(TAG, "Application " + data.info.getPackageName()
                      + " can be debugged on port 8100...");
            }
        }

        // Allow application-generated systrace messages if we're debuggable.
        boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        Trace.setAppTracingAllowed(isAppDebuggable);
        if (isAppDebuggable && data.enableBinderTracking) {
            Binder.enableTracing();
        }

        /**
         * Initialize the default http proxy in this process for the reasons we set the time zone.
         */
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
        final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        if (b != null) {
            // In pre-boot mode (doing initial launch to collect password), not
            // all system is up.  This includes the connectivity service, so don't
            // crash if we can't get it.
            final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
            try {
                final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
                Proxy.setHttpProxySystemProperty(proxyInfo);
            } catch (RemoteException e) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw e.rethrowFromSystemServer();
            }
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Instrumentation info affects the class loader, so load it before
        // setting up the app context.
        final InstrumentationInfo ii;
        if (data.instrumentationName != null) {
            try {
                ii = new ApplicationPackageManager(null, getPackageManager())
                        .getInstrumentationInfo(data.instrumentationName, 0);
            } catch (PackageManager.NameNotFoundException e) {
                throw new RuntimeException(
                        "Unable to find instrumentation info for: " + data.instrumentationName);
            }

            mInstrumentationPackageName = ii.packageName;
            mInstrumentationAppDir = ii.sourceDir;
            mInstrumentationSplitAppDirs = ii.splitSourceDirs;
            mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
            mInstrumentedAppDir = data.info.getAppDir();
            mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
            mInstrumentedLibDir = data.info.getLibDir();
        } else {
            ii = null;
        }

        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        updateLocaleListFromAppContext(appContext,
                mResourcesManager.getConfiguration().getLocales());

        if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
            // This cache location probably points at credential-encrypted
            // storage which may not be accessible yet; assign it anyway instead
            // of pointing at device-encrypted storage.
            final File cacheDir = appContext.getCacheDir();
            if (cacheDir != null) {
                // Provide a usable directory for temporary files
                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
            } else {
                Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
                        + "due to missing cache directory");
            }

            // Setup a location to store generated/compiled graphics code.
            final Context deviceContext = appContext.createDeviceProtectedStorageContext();
            final File codeCacheDir = deviceContext.getCodeCacheDir();
            if (codeCacheDir != null) {
                setupGraphicsSupport(data.info, codeCacheDir);
            } else {
                Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
            }
        }

        // Install the Network Security Config Provider. This must happen before the application
        // code is loaded to prevent issues with instances of TLS objects being created before
        // the provider is installed.
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
        NetworkSecurityConfigProvider.install(appContext);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Continue loading instrumentation.
        if (ii != null) {
            final ApplicationInfo instrApp = new ApplicationInfo();
            ii.copyTo(instrApp);
            instrApp.initForUser(UserHandle.myUserId());
            final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

            try {
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
                throw new RuntimeException(
                    "Unable to instantiate instrumentation "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            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();
        }

        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
        } else {
            // Small heap, clamp to the current growth limit and let the heap release
            // pages after the growth limit to the non growth limit capacity. b/18387825
            dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
        }

        // Allow disk access during application and provider setup. This could
        // block processing ordered broadcasts, but later processing would
        // probably end up doing the same disk access.
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        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;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            // 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) {
                throw new RuntimeException(
                    "Exception thrown in onCreate() of "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

            try {
                mInstrumentation.callApplica,tionOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
           

在handleBindApplication中做了很多操作,建立配置資訊

mConfiguration = new Configuration(data.config);
    mCompatConfiguration = new Configuration(data.config);
           

設定目前程序名

Process.setArgV0(data.processName);
           

如果AsyncTask在小于3.0版本時設定預設的線程池(後期會講述線程和線程池的原理),

if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
        AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
           

在resources管理器中設定螢幕配置資訊

mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
        mCurDefaultDisplayDpi = data.config.densityDpi;

        // This calls mResourcesManager so keep it within the synchronized block.
        applyCompatConfiguration(mCurDefaultDisplayDpi);
           

嚴格規定網絡請求不能在UI線程中使用,也就是在Android 3.0之前可以在UI線程中實作網絡請求,3.0後網絡請求必須要放到子線程中,如果在Android 3.0之後在主線程中做網絡請求會抛NetworkOnMainThreadException

if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
        StrictMode.enableDeathOnNetwork();
    }
           

如果Android程式是Debug模式開啟Debug彈出 mgr.showWaitingForDebugger(mAppThread, true)

if (data.debugMode != IApplicationThread.DEBUG_OFF) {
        // XXX should have option to change the port.
        Debug.changeDebugPort(8100);
        if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
            Slog.w(TAG, "Application " + data.info.getPackageName()
                  + " is waiting for the debugger on port 8100...");

            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.showWaitingForDebugger(mAppThread, true);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }

            Debug.waitForDebugger();

            try {
                mgr.showWaitingForDebugger(mAppThread, false);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }

        } else {
            Slog.w(TAG, "Application " + data.info.getPackageName()
                  + " can be debugged on port 8100...");
        }
    }
           

建立InstrumentationInfo儲存應用程式包名,檔案目錄等資訊

final InstrumentationInfo ii;
            if (data.instrumentationName != null) {
                try {
                    ii = new ApplicationPackageManager(null, getPackageManager())
                            .getInstrumentationInfo(data.instrumentationName, 0);
                } catch (PackageManager.NameNotFoundException e) {
                    throw new RuntimeException(
                            "Unable to find instrumentation info for: " + data.instrumentationName);
                }

                mInstrumentationPackageName = ii.packageName;
                mInstrumentationAppDir = ii.sourceDir;
                mInstrumentationSplitAppDirs = ii.splitSourceDirs;
                mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
                mInstrumentedAppDir = data.info.getAppDir();
                mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
                mInstrumentedLibDir = data.info.getLibDir();
            } else {
                ii = null;
            }
           

建立ApplicationInfo資訊,拷貝InstrumentationInfo中的資訊到ApplicationInfo中,擷取LoadedApk安裝包資訊,建立ContextImpl對象後建立Instrumentation對象,在Instrumentation對象通過Instrumentation.init()方法注入ActivityThread,MessageQueue,ActivityMonitor等引用,後面講述應用程式内部開啟另一個Activity時會發現通過Instrumentation對象轉發startActivity操作.

// Continue loading instrumentation.
            if (ii != null) {
                final ApplicationInfo instrApp = new ApplicationInfo();
                ii.copyTo(instrApp);
                instrApp.initForUser(UserHandle.myUserId());
                final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true, false);
                final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

                try {
                    final ClassLoader cl = instrContext.getClassLoader();
                    mInstrumentation = (Instrumentation)
                        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(
                        "Unable to instantiate instrumentation "
                        + data.instrumentationName + ": " + e.toString(), e);
                }

                final ComponentName component = new ComponentName(ii.packageName, ii.name);
                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();
            }
           

通過LoadedApk對象擷取Application執行個體

Application app = data.info.makeApplication(data.restrictedBackupMode, null);
           

通過ApplicationInfo擷取到我們在AndroidManifest.xml中配置的Application實作類,擷取執行個體後建立ContextImpl執行個體,建立Application的執行個體(也就是我們在xml配置的application類)并且把ContextImpl注入到我們的實作類中,通過appContext.setOuterContext(app)方法設定ContextImpl中外圍context關聯,此時ContextImpl中有application執行個體,application中也有ContextImpl執行個體對象,然後調用application中的onCreate方法。ContextImpl和我們建立的Activity之間使用裝飾者模式關聯。可以學習《Android源碼設計模式解析和實戰》《Head Frist設計模式》學習設計模式。

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) {
                if (!mActivityThread.mInstrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to instantiate application " + appClass
                        + ": " + e.toString(), e);
                }
            }
            mActivityThread.mAllApplications.add(app);
            mApplication = app;

            if (instrumentation != null) {
                try {
                    instrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!instrumentation.onException(app, e)) {
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                            + ": " + e.toString(), e);
                    }
                }
            }

            // Rewrite the R 'constants' for all library apks.
            SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
                    .getAssignedPackageIdentifiers();
            final int N = packageIdentifiers.size();
            for (int i = 0; i < N; i++) {
                final int id = packageIdentifiers.keyAt(i);
                if (id == 0x01 || id == 0x7f) {
                    continue;
                }

                rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
            }

            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

            return app;
}
           

在此Application類已經建立了,接着回到傳回到ActivityManagerService中的attachApplicationLocked方法,接着調用mStackSupervisor中的attachApplicationLocked方法,我們知道Android中有Activit建立後都會放在任務棧(ActivityStack)中,在ActivityStack中維護一個TaskRecord集合,每個TaskRecord代表我們建立的一個Task任務棧,而我們的Activity入棧後,都會通過建立ActivityRecord對象儲存Activity中的資訊,我們在不同的應用程式中可以通過設定Affinity屬于把不同應用程序的Activity放到同一個任務棧中

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

前面提到normalMode是true,調用mStackSupervisor.attachApplicationLocked(app)方法,此時進入到ActivityStackSupervisor Activity的堆棧管理類中,在這裡會周遊所用TaskRecord任務棧,擷取到前台任務棧,擷取到前台任務棧中頂部的Activity記錄資訊,判斷棧頂Activity的程序和app程序是否相同等資訊

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

在這裡realStartActivityLocked()方法才是正真開啟Activity

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {

            if (!allPausedActivitiesComplete()) {
                // While there are activities pausing we skipping starting any new activities until
                // pauses are complete. NOTE: that we also do this for activities that are starting in
                // the paused state because they will first be resumed then paused on the client side.
                if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                        "realStartActivityLocked: Skipping start of r=" + r
                        + " some activities pausing...");
                return false;
            }

            if (andResume) {
                r.startFreezingScreenLocked(app, 0);
                mWindowManager.setAppVisibility(r.appToken, true);

                // schedule launch ticks to collect information about slow apps.
                r.startLaunchTickingLocked();
            }

            // Have the window manager re-evaluate the orientation of
            // the screen based on the new activity order.  Note that
            // as a result of this, it can call back into the activity
            // manager with a new orientation.  We don't care about that,
            // because the activity is not currently running so we are
            // just restarting it anyway.
            if (checkConfig) {
                Configuration config = mWindowManager.updateOrientationFromAppTokens(
                        mService.mConfiguration,
                        r.mayFreezeScreenLocked(app) ? r.appToken : null);
                // Deferring resume here because we're going to launch new activity shortly.
                // We don't want to perform a redundant launch of the same record while ensuring
                // configurations and trying to resume top activity of focused stack.
                mService.updateConfigurationLocked(config, r, false, true /* deferResume */);
            }

            r.app = app;
            app.waitingToKill = null;
            r.launchCount++;
            r.lastLaunchTime = SystemClock.uptimeMillis();

            if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

            int idx = app.activities.indexOf(r);
            if (idx < 0) {
                app.activities.add(r);
            }
            mService.updateLruProcessLocked(app, true, null);
            mService.updateOomAdjLocked();

            final TaskRecord task = r.task;
            if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                    task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
                setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
            }

            final ActivityStack stack = task.stack;
            try {
                if (app.thread == null) {
                    throw new RemoteException();
                }
                List<ResultInfo> results = null;
                List<ReferrerIntent> newIntents = null;
                if (andResume) {
                    results = r.results;
                    newIntents = r.newIntents;
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                        "Launching: " + r + " icicle=" + r.icicle + " with results=" + results
                        + " newIntents=" + newIntents + " andResume=" + andResume);
                if (andResume) {
                    EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
                            r.userId, System.identityHashCode(r),
                            task.taskId, r.shortComponentName);
                }
                if (r.isHomeActivity()) {
                    // Home process is the root process of the task.
                    mService.mHomeProcess = task.mActivities.get(0).app;
                }
                mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                          PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
                r.sleeping = false;
                r.forceNewConfig = false;
                mService.showUnsupportedZoomDialogIfNeededLocked(r);
                mService.showAskCompatModeDialogLocked(r);
                r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
                ProfilerInfo profilerInfo = null;
                if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                    if (mService.mProfileProc == null || mService.mProfileProc == app) {
                        mService.mProfileProc = app;
                        final String profileFile = mService.mProfileFile;
                        if (profileFile != null) {
                            ParcelFileDescriptor profileFd = mService.mProfileFd;
                            if (profileFd != null) {
                                try {
                                    profileFd = profileFd.dup();
                                } catch (IOException e) {
                                    if (profileFd != null) {
                                        try {
                                            profileFd.close();
                                        } catch (IOException o) {
                                        }
                                        profileFd = null;
                                    }
                                }
                            }

                            profilerInfo = new ProfilerInfo(profileFile, profileFd,
                                    mService.mSamplingInterval, mService.mAutoStopProfiler);
                        }
                    }
                }

                if (andResume) {
                    app.hasShownUi = true;
                    app.pendingUiClean = true;
                }
                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);

                if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                    // This may be a heavy-weight process!  Note that the package
                    // manager will ensure that only activity can run in the main
                    // process of the .apk, which is the only thing that will be
                    // considered heavy-weight.
                    if (app.processName.equals(app.info.packageName)) {
                        if (mService.mHeavyWeightProcess != null
                                && mService.mHeavyWeightProcess != app) {
                            Slog.w(TAG, "Starting new heavy weight process " + app
                                    + " when already running "
                                    + mService.mHeavyWeightProcess);
                        }
                        mService.mHeavyWeightProcess = app;
                        Message msg = mService.mHandler.obtainMessage(
                                ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
                        msg.obj = r;
                        mService.mHandler.sendMessage(msg);
                    }
                }

            } catch (RemoteException e) {
                if (r.launchFailed) {
                    // This is the second time we failed -- finish activity
                    // and give up.
                    Slog.e(TAG, "Second failure launching "
                          + r.intent.getComponent().flattenToShortString()
                          + ", giving up", e);
                    mService.appDiedLocked(app);
                    stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                            "2nd-crash", false);
                    return false;
                }

                // This is the first time we failed -- restart process and
                // retry.
                app.activities.remove(r);
                throw e;
            }

            r.launchFailed = false;
            if (stack.updateLRUListLocked(r)) {
                Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
            }

            if (andResume) {
                // As part of the process of launching, ActivityThread also performs
                // a resume.
                stack.minimalResumeActivityLocked(r);
            } else {
                // This activity is not starting in the resumed state... which should look like we asked
                // it to pause+stop (but remain visible), and it has done so and reported back the
                // current icicle and other state.
                if (DEBUG_STATES) Slog.v(TAG_STATES,
                        "Moving to PAUSED: " + r + " (starting in paused state)");
                r.state = PAUSED;
            }

            // Launch the new version setup screen if needed.  We do this -after-
            // launching the initial activity (that is, home), so that it can have
            // a chance to initialize itself while in the background, making the
            // switch back to it faster and look better.
            if (isFocusedStack(stack)) {
                mService.startSetupActivityLocked();
            }

            // Update any services we are bound to that might care about whether
            // their client may have activities.
            if (r.app != null) {
                mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
            }

            return true;
}
           

在realStartActivityLocked方法中通過調用app.thread.scheduleLaunchActivity()方法通過遠端調用ActivityThread中kApplicationThread的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;
                r.persistentState = persistentState;

                r.pendingResults = pendingResults;
                r.pendingIntents = pendingNewIntents;

                r.startsNotResumed = notResumed;
                r.isForward = isForward;

                r.profilerInfo = profilerInfo;

                r.overrideConfig = overrideConfig;
                updatePendingConfiguration(curConfig);

                sendMessage(H.LAUNCH_ACTIVITY, r);
    }
           

通過向mH中發送一個what為LAUNCH_ACTIVITY消息,在前面mH裡面handleMessage方法中調用handleLaunchActivity方法,進入ActivityThread中的handleLaunchActivity方法

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            // 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();

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

                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.
                    performPauseActivityIfNeeded(r, reason);

                    // 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;
                    }
                }
            } 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,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
    }
           

可以看到在handleLaunchActivity調用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 (r.overrideConfig != null) {
                        config.updateFrom(r.overrideConfig);
                    }
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                            + r.activityInfo.name + " with config " + config);
                    Window window = null;
                    if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                        window = r.mPendingRemoveWindow;
                        r.mPendingRemoveWindow = null;
                        r.mPendingRemoveWindowManager = null;
                    }
                    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 (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;
}
           

通過mInstrumentation.newActivity建立Activity執行個體,并且通過調用attach進行綁定

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

在attach中會把ContextImpl設定給Activity的mBase,是以我們在使用Activity的context時實際使用的是contextImpl類中的資料。至此Activity的建立已經完成。在oncreate以後會調用Activity的onCreate方法,在調用onCreate方法時會判斷Bundle中是否用資料,如果有調用時把Bundle傳遞給實作Activity的類進行資料回顯

if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
           

判斷目前Activity是否finsh,如果沒有finsh調用onstart

if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
        }
           

在此Activity的oncreate和onstart方法調用完成,在ActivityThread中handleLaunchActivity方法接着會調用handleResumeActivity方法

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

        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.
            performPauseActivityIfNeeded(r, reason);

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

在handleResumeActivity方法中調用performResumeActivity方法把事件分發給Activity中的performResume方法,調用onResume方法,在handleResumeActivity方法中會調用Window進行界面繪制。整個應用程式從application和mainActivity啟動到Activity的onCreate,onStart和onRusume方法調用,至于onPause,onStop和onDestroy的調用可以學習應用程式中内部Activity事件分發機制http://blog.csdn.net/luoshengyang/article/details/6703247。

繼續閱讀