android app的启动流程

开始

如图侵删


app启动流程
1.点击图标

①当用户点击应用图标时,会启动launcher应用程序(Launcher继承自Activity,实现了点击长按监听),此时Luncher会通过Intent发送startActivity请求,通过binder机制调用ActivityManagerService通讯,经过一系列操作,最后调用startProcessLocked方法通过Socket通道传递参数给Zygote进程。

②这时,Zygote进程就会调用ZygoteInit.mian()产生一个新的进程并返回pid,调用ActivityThread.main来实例化ActivityThread对象。

此时Activity进程会真正开始,那么接下来看一看它到底干了什么?

ActivityThread.main函数

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>");
    //1.看这里,这里创建了一个主线程,贯穿整个app生命周期
    Looper.prepareMainLooper();
    //2.创建了Activity线程,并执行attach方法。
    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循环
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

上述代码中有三句关键代码:

    //1.看这里,这里创建了一个主线程,贯穿整个app生命周期
    Looper.prepareMainLooper();
    //2.创建了Activity线程,并执行attach方法。
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    //3.开启looper循环
    Looper.loop();

android系统是基于消息队列机制运行的,所以在Activity线程启动后立即启动消息循环。

可以看到执行了thread.attach方法,那么这里又发生了哪些事情呢?

//步骤①
final IActivityManager mgr = ActivityManager.getService();
try {
    //步骤②
    mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
    throw ex.rethrowFromSystemServer();
}

步骤①中,通过getService获取ActivityManager:

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

可以看到,由于ActivityManagerService是在system_server进程中,所以需要通过binder机制获取到ActivityManagerService服务

步骤②attachApplication调用了attachApplicationLocked方法。而这个attachApplicationLocked方法绑定ActivityThread和ApplicationThread并做了一个初始化的工作。

最后attachApplicationLocked方法调用:

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

那么mStackSupervisor.attachApplicationLocked(app)做了哪些工作呢?

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            //获取次应用的所有Activity
            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) {
                    //如果与指定包名相同的 则启动activity
                    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;
    }

由此可见 activity的启动则是在realStartActivityLocked函数里面:
realStartActivityLocked函数做了很多工作,比如加入到activitys栈里面,是否resume等等。
最终的最终是下面这一行代码:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global and
        // override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, !andResume,
        mService.isNextTransitionForward(), profilerInfo);

这个app.thread正是我们ActivityThread里面持有的一个ApplicationThread实例,你会发现四大组件的所有的启动方式都在这里调用:

private class ApplicationThread extends IApplicationThread.Stub {
    private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

    private int mLastProcessState = -1;

    private void updatePendingConfiguration(Configuration config) {
        synchronized (mResourcesManager) {
            if (mPendingConfiguration == null ||
                    mPendingConfiguration.isOtherSeqNewer(config)) {
                mPendingConfiguration = config;
            }
        }
    }

    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        int seq = getLifecycleSeq();
        if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                + " operation received seq: " + seq);
        sendMessage(
                finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                token,
                (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                configChanges,
                seq);
    }

    public final void scheduleStopActivity(IBinder token, boolean showWindow,
            int configChanges) {
        int seq = getLifecycleSeq();
        if (DEBUG_ORDER) Slog.d(TAG, "stopActivity " + ActivityThread.this
                + " operation received seq: " + seq);
        sendMessage(
            showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
            token, 0, configChanges, seq);
    }

    public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
        sendMessage(
            showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
            token);
    }

    public final void scheduleSleeping(IBinder token, boolean sleeping) {
        sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
    }

    public final void scheduleResumeActivity(IBinder token, int processState,
            boolean isForward, Bundle resumeArgs) {
        int seq = getLifecycleSeq();
        if (DEBUG_ORDER) Slog.d(TAG, "resumeActivity " + ActivityThread.this
                + " operation received seq: " + seq);
        updateProcessState(processState, false);
        sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq);
    }

    public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
        ResultData res = new ResultData();
        res.token = token;
        res.results = results;
        sendMessage(H.SEND_RESULT, res);
    }

    // we use token to identify this activity without having to send the
    // activity itself back to the activity manager. (matters more with ipc)
    @Override
    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);
    }

    @Override
    public final void scheduleRelaunchActivity(IBinder token,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            int configChanges, boolean notResumed, Configuration config,
            Configuration overrideConfig, boolean preserveWindow) {
        requestRelaunchActivity(token, pendingResults, pendingNewIntents,
                configChanges, notResumed, config, overrideConfig, true, preserveWindow);
    }

    public final void scheduleNewIntent(
            List<ReferrerIntent> intents, IBinder token, boolean andPause) {
        NewIntentData data = new NewIntentData();
        data.intents = intents;
        data.token = token;
        data.andPause = andPause;

        sendMessage(H.NEW_INTENT, data);
    }

    public final void scheduleDestroyActivity(IBinder token, boolean finishing,
            int configChanges) {
        sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
                configChanges);
    }

    public final void scheduleReceiver(Intent intent, ActivityInfo info,
            CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
            boolean sync, int sendingUser, int processState) {
        updateProcessState(processState, false);
        ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
                sync, false, mAppThread.asBinder(), sendingUser);
        r.info = info;
        r.compatInfo = compatInfo;
        sendMessage(H.RECEIVER, r);
    }

    public final void scheduleCreateBackupAgent(ApplicationInfo app,
            CompatibilityInfo compatInfo, int backupMode) {
        CreateBackupAgentData d = new CreateBackupAgentData();
        d.appInfo = app;
        d.compatInfo = compatInfo;
        d.backupMode = backupMode;

        sendMessage(H.CREATE_BACKUP_AGENT, d);
    }

    public final void scheduleDestroyBackupAgent(ApplicationInfo app,
            CompatibilityInfo compatInfo) {
        CreateBackupAgentData d = new CreateBackupAgentData();
        d.appInfo = app;
        d.compatInfo = compatInfo;

        sendMessage(H.DESTROY_BACKUP_AGENT, d);
    }

    public final void scheduleCreateService(IBinder token,
            ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
        updateProcessState(processState, false);
        CreateServiceData s = new CreateServiceData();
        s.token = token;
        s.info = info;
        s.compatInfo = compatInfo;

        sendMessage(H.CREATE_SERVICE, s);
    }

    public final void scheduleBindService(IBinder token, Intent intent,
            boolean rebind, int processState) {
        updateProcessState(processState, false);
        BindServiceData s = new BindServiceData();
        s.token = token;
        s.intent = intent;
        s.rebind = rebind;

        if (DEBUG_SERVICE)
            Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                    + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
        sendMessage(H.BIND_SERVICE, s);
    }

    public final void scheduleUnbindService(IBinder token, Intent intent) {
        BindServiceData s = new BindServiceData();
        s.token = token;
        s.intent = intent;

        sendMessage(H.UNBIND_SERVICE, s);
    }

    public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
        List<ServiceStartArgs> list = args.getList();

        for (int i = 0; i < list.size(); i++) {
            ServiceStartArgs ssa = list.get(i);
            ServiceArgsData s = new ServiceArgsData();
            s.token = token;
            s.taskRemoved = ssa.taskRemoved;
            s.startId = ssa.startId;
            s.flags = ssa.flags;
            s.args = ssa.args;

            sendMessage(H.SERVICE_ARGS, s);
        }
    }

    public final void scheduleStopService(IBinder token) {
        sendMessage(H.STOP_SERVICE, token);
    }

    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 services, Bundle coreSettings,
            String buildSerial) {

        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;
        data.buildSerial = buildSerial;
        sendMessage(H.BIND_APPLICATION, data);
    }

    public final void scheduleExit() {
        sendMessage(H.EXIT_APPLICATION, null);
    }

    public final void scheduleSuicide() {
        sendMessage(H.SUICIDE, null);
    }

    public void scheduleConfigurationChanged(Configuration config) {
        updatePendingConfiguration(config);
        sendMessage(H.CONFIGURATION_CHANGED, config);
    }

    public void scheduleApplicationInfoChanged(ApplicationInfo ai) {
        sendMessage(H.APPLICATION_INFO_CHANGED, ai);
    }

    public void updateTimeZone() {
        TimeZone.setDefault(null);
    }

    public void clearDnsCache() {
        // a non-standard API to get this to libcore
        InetAddress.clearDnsCache();
        // Allow libcore to perform the necessary actions as it sees fit upon a network
        // configuration change.
        NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged();
    }

    public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) {
        final ConnectivityManager cm = ConnectivityManager.from(getSystemContext());
        final Network network = cm.getBoundNetworkForProcess();
        if (network != null) {
            Proxy.setHttpProxySystemProperty(cm.getDefaultProxy());
        } else {
            Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
        }
    }

    public void processInBackground() {
        mH.removeMessages(H.GC_WHEN_IDLE);
        mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
    }

    public void dumpService(ParcelFileDescriptor pfd, IBinder servicetoken, String[] args) {
        DumpComponentInfo data = new DumpComponentInfo();
        try {
            data.fd = pfd.dup();
            data.token = servicetoken;
            data.args = args;
            sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/);
        } catch (IOException e) {
            Slog.w(TAG, "dumpService failed", e);
        } finally {
            IoUtils.closeQuietly(pfd);
        }
    }

    // This function exists to make sure all receiver dispatching is
    // correctly ordered, since these are one-way calls and the binder driver
    // applies transaction ordering per object for such calls.
    public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
            int resultCode, String dataStr, Bundle extras, boolean ordered,
            boolean sticky, int sendingUser, int processState) throws RemoteException {
        updateProcessState(processState, false);
        receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                sticky, sendingUser);
    }

    @Override
    public void scheduleLowMemory() {
        sendMessage(H.LOW_MEMORY, null);
    }

    @Override
    public void scheduleActivityConfigurationChanged(
            IBinder token, Configuration overrideConfig) {
        sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED,
                new ActivityConfigChangeData(token, overrideConfig));
    }

    @Override
    public void scheduleActivityMovedToDisplay(IBinder token, int displayId,
            Configuration overrideConfig) {
        sendMessage(H.ACTIVITY_MOVED_TO_DISPLAY,
                new ActivityConfigChangeData(token, overrideConfig), displayId);
    }

    @Override
    public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
        sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType);
    }

    public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
        DumpHeapData dhd = new DumpHeapData();
        dhd.path = path;
        dhd.fd = fd;
        sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/);
    }

    public void attachAgent(String agent) {
        sendMessage(H.ATTACH_AGENT, agent);
    }

    public void setSchedulingGroup(int group) {
        // Note: do this immediately, since going into the foreground
        // should happen regardless of what pending work we have to do
        // and the activity manager will wait for us to report back that
        // we are done before sending us to the background.
        try {
            Process.setProcessGroup(Process.myPid(), group);
        } catch (Exception e) {
            Slog.w(TAG, "Failed setting process group to " + group, e);
        }
    }

    public void dispatchPackageBroadcast(int cmd, String[] packages) {
        sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
    }

    public void scheduleCrash(String msg) {
        sendMessage(H.SCHEDULE_CRASH, msg);
    }

    public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
            String prefix, String[] args) {
        DumpComponentInfo data = new DumpComponentInfo();
        try {
            data.fd = pfd.dup();
            data.token = activitytoken;
            data.prefix = prefix;
            data.args = args;
            sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/);
        } catch (IOException e) {
            Slog.w(TAG, "dumpActivity failed", e);
        } finally {
            IoUtils.closeQuietly(pfd);
        }
    }

    public void dumpProvider(ParcelFileDescriptor pfd, IBinder providertoken,
            String[] args) {
        DumpComponentInfo data = new DumpComponentInfo();
        try {
            data.fd = pfd.dup();
            data.token = providertoken;
            data.args = args;
            sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/);
        } catch (IOException e) {
            Slog.w(TAG, "dumpProvider failed", e);
        } finally {
            IoUtils.closeQuietly(pfd);
        }
    }

    @Override
    public void dumpMemInfo(ParcelFileDescriptor pfd, Debug.MemoryInfo mem, boolean checkin,
            boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
            boolean dumpUnreachable, String[] args) {
        FileOutputStream fout = new FileOutputStream(pfd.getFileDescriptor());
        PrintWriter pw = new FastPrintWriter(fout);
        try {
            dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
        } finally {
            pw.flush();
            IoUtils.closeQuietly(pfd);
        }
    }

    private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
            boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
        long nativeMax = Debug.getNativeHeapSize() / 1024;
        long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
        long nativeFree = Debug.getNativeHeapFreeSize() / 1024;

        Runtime runtime = Runtime.getRuntime();
        runtime.gc();  // Do GC since countInstancesOfClass counts unreachable objects.
        long dalvikMax = runtime.totalMemory() / 1024;
        long dalvikFree = runtime.freeMemory() / 1024;
        long dalvikAllocated = dalvikMax - dalvikFree;

        Class[] classesToCount = new Class[] {
                ContextImpl.class,
                Activity.class,
                WebView.class,
                OpenSSLSocketImpl.class
        };
        long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
        long appContextInstanceCount = instanceCounts[0];
        long activityInstanceCount = instanceCounts[1];
        long webviewInstanceCount = instanceCounts[2];
        long openSslSocketCount = instanceCounts[3];

        long viewInstanceCount = ViewDebug.getViewInstanceCount();
        long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
        int globalAssetCount = AssetManager.getGlobalAssetCount();
        int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
        int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
        int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
        int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
        long parcelSize = Parcel.getGlobalAllocSize();
        long parcelCount = Parcel.getGlobalAllocCount();
        SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();

        dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
                Process.myPid(),
                (mBoundApplication != null) ? mBoundApplication.processName : "unknown",
                nativeMax, nativeAllocated, nativeFree,
                dalvikMax, dalvikAllocated, dalvikFree);

        if (checkin) {
            // NOTE: if you change anything significant below, also consider changing
            // ACTIVITY_THREAD_CHECKIN_VERSION.

            // Object counts
            pw.print(viewInstanceCount); pw.print(',');
            pw.print(viewRootInstanceCount); pw.print(',');
            pw.print(appContextInstanceCount); pw.print(',');
            pw.print(activityInstanceCount); pw.print(',');

            pw.print(globalAssetCount); pw.print(',');
            pw.print(globalAssetManagerCount); pw.print(',');
            pw.print(binderLocalObjectCount); pw.print(',');
            pw.print(binderProxyObjectCount); pw.print(',');

            pw.print(binderDeathObjectCount); pw.print(',');
            pw.print(openSslSocketCount); pw.print(',');

            // SQL
            pw.print(stats.memoryUsed / 1024); pw.print(',');
            pw.print(stats.memoryUsed / 1024); pw.print(',');
            pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
            pw.print(stats.largestMemAlloc / 1024);
            for (int i = 0; i < stats.dbStats.size(); i++) {
                DbStats dbStats = stats.dbStats.get(i);
                pw.print(','); pw.print(dbStats.dbName);
                pw.print(','); pw.print(dbStats.pageSize);
                pw.print(','); pw.print(dbStats.dbSize);
                pw.print(','); pw.print(dbStats.lookaside);
                pw.print(','); pw.print(dbStats.cache);
                pw.print(','); pw.print(dbStats.cache);
            }
            pw.println();

            return;
        }

        pw.println(" ");
        pw.println(" Objects");
        printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
                viewRootInstanceCount);

        printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
                "Activities:", activityInstanceCount);

        printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
                "AssetManagers:", globalAssetManagerCount);

        printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
                "Proxy Binders:", binderProxyObjectCount);
        printRow(pw, TWO_COUNT_COLUMNS, "Parcel memory:", parcelSize/1024,
                "Parcel count:", parcelCount);
        printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount,
                "OpenSSL Sockets:", openSslSocketCount);
        printRow(pw, ONE_COUNT_COLUMN, "WebViews:", webviewInstanceCount);

        // SQLite mem info
        pw.println(" ");
        pw.println(" SQL");
        printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
        printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
                stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
        pw.println(" ");
        int N = stats.dbStats.size();
        if (N > 0) {
            pw.println(" DATABASES");
            printRow(pw, "  %8s %8s %14s %14s  %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
                    "Dbname");
            for (int i = 0; i < N; i++) {
                DbStats dbStats = stats.dbStats.get(i);
                printRow(pw, DB_INFO_FORMAT,
                        (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
                        (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
                        (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
                        dbStats.cache, dbStats.dbName);
            }
        }

        // Asset details.
        String assetAlloc = AssetManager.getAssetAllocations();
        if (assetAlloc != null) {
            pw.println(" ");
            pw.println(" Asset Allocations");
            pw.print(assetAlloc);
        }

        // Unreachable native memory
        if (dumpUnreachable) {
            boolean showContents = ((mBoundApplication != null)
                && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
                || android.os.Build.IS_DEBUGGABLE;
            pw.println(" ");
            pw.println(" Unreachable memory");
            pw.print(Debug.getUnreachableMemory(100, showContents));
        }
    }

    @Override
    public void dumpGfxInfo(ParcelFileDescriptor pfd, String[] args) {
        nDumpGraphicsInfo(pfd.getFileDescriptor());
        WindowManagerGlobal.getInstance().dumpGfxInfo(pfd.getFileDescriptor(), args);
        IoUtils.closeQuietly(pfd);
    }

    private void dumpDatabaseInfo(ParcelFileDescriptor pfd, String[] args) {
        PrintWriter pw = new FastPrintWriter(
                new FileOutputStream(pfd.getFileDescriptor()));
        PrintWriterPrinter printer = new PrintWriterPrinter(pw);
        SQLiteDebug.dump(printer, args);
        pw.flush();
    }

    @Override
    public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) {
        if (mSystemThread) {
            // Ensure this invocation is asynchronous to prevent writer waiting if buffer cannot
            // be consumed. But it must duplicate the file descriptor first, since caller might
            // be closing it.
            final ParcelFileDescriptor dup;
            try {
                dup = pfd.dup();
            } catch (IOException e) {
                Log.w(TAG, "Could not dup FD " + pfd.getFileDescriptor().getInt$());
                return;
            } finally {
                IoUtils.closeQuietly(pfd);
            }

            AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        dumpDatabaseInfo(dup, args);
                    } finally {
                        IoUtils.closeQuietly(dup);
                    }
                }
            });
        } else {
            dumpDatabaseInfo(pfd, args);
            IoUtils.closeQuietly(pfd);
        }
    }

    @Override
    public void unstableProviderDied(IBinder provider) {
        sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
    }

    @Override
    public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
            int requestType, int sessionId, int flags) {
        RequestAssistContextExtras cmd = new RequestAssistContextExtras();
        cmd.activityToken = activityToken;
        cmd.requestToken = requestToken;
        cmd.requestType = requestType;
        cmd.sessionId = sessionId;
        cmd.flags = flags;
        sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
    }

    public void setCoreSettings(Bundle coreSettings) {
        sendMessage(H.SET_CORE_SETTINGS, coreSettings);
    }

    public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
        UpdateCompatibilityData ucd = new UpdateCompatibilityData();
        ucd.pkg = pkg;
        ucd.info = info;
        sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
    }

    public void scheduleTrimMemory(int level) {
        sendMessage(H.TRIM_MEMORY, null, level);
    }

    public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
        sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
    }

    public void scheduleOnNewActivityOptions(IBinder token, Bundle options) {
        sendMessage(H.ON_NEW_ACTIVITY_OPTIONS,
                new Pair<IBinder, ActivityOptions>(token, ActivityOptions.fromBundle(options)));
    }

    public void setProcessState(int state) {
        updateProcessState(state, true);
    }

    public void updateProcessState(int processState, boolean fromIpc) {
        synchronized (this) {
            if (mLastProcessState != processState) {
                mLastProcessState = processState;
                // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
                final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
                final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
                int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;
                // TODO: Tune this since things like gmail sync are important background but not jank perceptible.
                if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                    dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;
                }
                VMRuntime.getRuntime().updateProcessState(dalvikProcessState);
                if (false) {
                    Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
                            + (fromIpc ? " (from ipc": ""));
                }
            }
        }
    }

    /**
     * Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
     * the main thread that it needs to wait for the network rules to get updated before
     * launching an activity.
     */
    @Override
    public void setNetworkBlockSeq(long procStateSeq) {
        synchronized (mNetworkPolicyLock) {
            mNetworkBlockSeq = procStateSeq;
        }
    }

    @Override
    public void scheduleInstallProvider(ProviderInfo provider) {
        sendMessage(H.INSTALL_PROVIDER, provider);
    }

    @Override
    public final void updateTimePrefs(int timeFormatPreference) {
        final Boolean timeFormatPreferenceBool;
        // For convenience we are using the Intent extra values.
        if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR) {
            timeFormatPreferenceBool = Boolean.FALSE;
        } else if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR) {
            timeFormatPreferenceBool = Boolean.TRUE;
        } else {
            // timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT
            // (or unknown).
            timeFormatPreferenceBool = null;
        }
        DateFormat.set24HourTimePref(timeFormatPreferenceBool);
    }

    @Override
    public void scheduleCancelVisibleBehind(IBinder token) {
        sendMessage(H.CANCEL_VISIBLE_BEHIND, token);
    }

    @Override
    public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean visible) {
        sendMessage(H.BACKGROUND_VISIBLE_BEHIND_CHANGED, token, visible ? 1 : 0);
    }

    @Override
    public void scheduleEnterAnimationComplete(IBinder token) {
        sendMessage(H.ENTER_ANIMATION_COMPLETE, token);
    }

    @Override
    public void notifyCleartextNetwork(byte[] firstPacket) {
        if (StrictMode.vmCleartextNetworkEnabled()) {
            StrictMode.onCleartextNetworkDetected(firstPacket);
        }
    }

    @Override
    public void startBinderTracking() {
        sendMessage(H.START_BINDER_TRACKING, null);
    }

    @Override
    public void stopBinderTrackingAndDump(ParcelFileDescriptor pfd) {
        try {
            sendMessage(H.STOP_BINDER_TRACKING_AND_DUMP, pfd.dup());
        } catch (IOException e) {
        } finally {
            IoUtils.closeQuietly(pfd);
        }
    }

    @Override
    public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
            Configuration overrideConfig) throws RemoteException {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = token;
        args.arg2 = overrideConfig;
        args.argi1 = isInMultiWindowMode ? 1 : 0;
        sendMessage(H.MULTI_WINDOW_MODE_CHANGED, args);
    }

    @Override
    public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
            Configuration overrideConfig) throws RemoteException {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = token;
        args.arg2 = overrideConfig;
        args.argi1 = isInPipMode ? 1 : 0;
        sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, args);
    }

    @Override
    public void scheduleLocalVoiceInteractionStarted(IBinder token,
            IVoiceInteractor voiceInteractor) throws RemoteException {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = token;
        args.arg2 = voiceInteractor;
        sendMessage(H.LOCAL_VOICE_INTERACTION_STARTED, args);
    }

    @Override
    public void handleTrustStorageUpdate() {
        NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
    }
}

而且你们可以发现最后的最后都是通过sendMessage方法将消息发送给系统的handler进行处理.

public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    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 RELAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
            ActivityClientRecord r = (ActivityClientRecord)msg.obj;
            handleRelaunchActivity(r);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        case PAUSE_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
            SomeArgs args = (SomeArgs) msg.obj;
            handlePauseActivity((IBinder) args.arg1, false,
                    (args.argi1 & USER_LEAVING) != 0, args.argi2,
                    (args.argi1 & DONT_REPORT) != 0, args.argi3);
            maybeSnapshot();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
    }
}

你会发现handler调用了一个handleLaunchActivity方法处理activity的启动。在handleLaunchActivity里面又会调用performLaunchActivity方法:

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 {
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

private void reportSizeConfigurations(ActivityClientRecord r) {
    Configuration[] configurations = r.activity.getResources().getSizeConfigurations();
    if (configurations == null) {
        return;
    }
    SparseIntArray horizontal = new SparseIntArray();
    SparseIntArray vertical = new SparseIntArray();
    SparseIntArray smallest = new SparseIntArray();
    for (int i = configurations.length - 1; i >= 0; i--) {
        Configuration config = configurations[i];
        if (config.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
            vertical.put(config.screenHeightDp, 0);
        }
        if (config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
            horizontal.put(config.screenWidthDp, 0);
        }
        if (config.smallestScreenWidthDp != Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
            smallest.put(config.smallestScreenWidthDp, 0);
        }
    }
    try {
        ActivityManager.getService().reportSizeConfigurations(r.token,
                horizontal.copyKeys(), vertical.copyKeys(), smallest.copyKeys());
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }

}

最后我们会发现 activity是通过类反射机生产的一个对象:
mInstrumentation.newActivity

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

那么我们再回到handleLaunchActivity之中你会发现它里面顺序调用了
mInstrumentation.callActivityOnCreate;
r.activity.performResume;
mInstrumentation.callActivityOnPause;等等方法

最后在mInstrumentation.callActivityOnCreate方法中调用了:

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

而activity.performCreate方法中调用了onCreate方法,至此整个activity的启动至此圆满完成。

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