Activity冷啟動(dòng)流程

Activity啟動(dòng)流程

本文章基于Android6.0源碼

1. Activity冷啟動(dòng)

冷啟動(dòng)表示啟動(dòng)的時(shí)候沒(méi)有沒(méi)有當(dāng)前應(yīng)用進(jìn)程箱舞,需要首先啟動(dòng)進(jìn)程,然后再啟動(dòng)當(dāng)前Activity或者Service嘀粱,或者BroadCastReceiver奠骄。

2. Activity熱啟動(dòng)

表示當(dāng)前應(yīng)用進(jìn)程已經(jīng)起來(lái),只需要直接啟動(dòng)一個(gè)Activity剩瓶,service就行驹溃,

3. Activity啟動(dòng)的流程圖

本圖基于Android6.0源碼,如有疑問(wèn)歡迎留言延曙,并且歡迎提出問(wèn)題豌鹤,可以一同解答。 其實(shí)對(duì)著當(dāng)前這個(gè)流程圖已經(jīng)大致將Activity啟動(dòng)流程進(jìn)行了反應(yīng)枝缔。


Activity啟動(dòng)流程.png

存在問(wèn)題:

  • 目前缺少的是AMS通過(guò) Process.start 方法啟動(dòng)一個(gè)Process布疙, 這個(gè)Process是如何走到ActivityThread中去的
  • **ActivityStackSupervisor.startSpecificActivityLocked **這個(gè)方法是怎么進(jìn)去的,這里的處理很多愿卸,目前也不是很明白

4. 關(guān)鍵代碼解析

4.1 Activity.startActivity

 public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            //這里就直接走到Instrumenttation類(lèi)灵临,來(lái)執(zhí)行Start
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
        } else {
           // ...忽略
        }
    }

4.2 Instrumentation.execStartActivity

Instrumentation 儀器,樂(lè)譜)類(lèi)是一個(gè)非常關(guān)鍵的類(lèi)趴荸, 在一個(gè)進(jìn)程中儒溉,Activity生命周期的操作,甚至Application的生命周期的操作都是通過(guò)它來(lái)執(zhí)行的发钝,可以說(shuō) 他就是APP生命活動(dòng)的 樂(lè)譜顿涣。

 public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) { 
       //...省略一部分代碼
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

這里 ActivityManagerNative.getDefault() 這個(gè)方法其實(shí)去獲取到ActivityManagerProxy,來(lái)拿到AMS的代理類(lèi)酝豪,通過(guò)Binder來(lái)執(zhí)行跨進(jìn)程調(diào)用园骆,這里就是第一次發(fā)生跨進(jìn)程調(diào)用的地方。

Activity進(jìn)程 ---> SystemServer 進(jìn)程

這里順便提一下寓调,AMS是怎么把自己加入到ServiceManager中的锌唾。

  • ActivityManagerNative中是通過(guò) ServiceManageractivity名字來(lái)獲取到ActivityManagerProxy的client對(duì)象的。
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;
        }
    };
}

  • 在AMS啟動(dòng)過(guò)程中,會(huì)調(diào)用一個(gè)**setSystemProcess ** 在這里晌涕,AMS會(huì)把自己添加到服務(wù)端里面滋捶。

      public void setSystemProcess() {
            try {
                ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
                ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
                ServiceManager.addService("meminfo", new MemBinder(this));
                ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
                ServiceManager.addService("dbinfo", new DbBinder(this));
                if (MONITOR_CPU_USAGE) {
                    ServiceManager.addService("cpuinfo", new CpuBinder(this));
                }
                ServiceManager.addService("permission", new PermissionController(this));
                ServiceManager.addService("processinfo", new ProcessInfoService(this));
    
                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                        "android", STOCK_PM_FLAGS);
                mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
    
                synchronized (this) {
                    ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                    app.persistent = true;
                    app.pid = MY_PID;
                    app.maxAdj = ProcessList.SYSTEM_ADJ;
                    app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                    synchronized (mPidsSelfLocked) {
                        mPidsSelfLocked.put(app.pid, app);
                    }
                    updateLruProcessLocked(app, false, null);
                    updateOomAdjLocked();
                }
            } catch (PackageManager.NameNotFoundException e) {
                throw new RuntimeException(
                        "Unable to find android system package", e);
            }
        }
    
    

4.3 AMS 執(zhí)行Activity啟動(dòng)

通過(guò)一次跨進(jìn)程Binder調(diào)用之后,AMS開(kāi)始執(zhí)行startActivity流程余黎。這里基本沒(méi)有什么. Android6.0 已經(jīng)將之前很多復(fù)雜的啟動(dòng)流程進(jìn)行了優(yōu)化(少了ActiivtyStarter,等等類(lèi))重窟,但是基本的流程是不變的。

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

4.4 ActivityStackSupervisor

 ActivityStackSupervisor在真實(shí)啟動(dòng)Activity之前惧财,會(huì)針對(duì)Intent來(lái)進(jìn)行Resolve巡扇,將 Intent指向 的啟動(dòng)類(lèi) 通過(guò)PMS(PackageManagerServcie) 來(lái)解析出來(lái)。如果找不到響應(yīng)當(dāng)前Intent的類(lèi)垮衷,那么就會(huì)報(bào)啟動(dòng)異常

*  如果執(zhí)行錯(cuò)誤厅翔,會(huì)將錯(cuò)誤結(jié)果返回給 **Instrumentation** 調(diào)用    **checkStartActivityResult(result, intent);**
   final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        boolean componentSpecified = intent.getComponent() != null;

        // Don't modify the client's object!
        intent = new Intent(intent);

        // Collect information about the target of the Intent 
        //這里針對(duì)當(dāng)前的intentn進(jìn)行一次解析,涉及到了PMS(Actiivty安裝管理流程) 
        //如果這里針對(duì)intent解析沒(méi)有出來(lái)搀突, 就可能拋出異常表示沒(méi)有找到目標(biāo)Activity
        ActivityInfo aInfo =
                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

        ActivityContainer container = (ActivityContainer)iContainer;
      // 這里解析之后刀闷,就執(zhí)行 startActivityLocked.

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
        }
   }

執(zhí)行startActivityLocked

這個(gè)方法比較長(zhǎng),但是發(fā)現(xiàn)Android源碼中一個(gè)比較好的點(diǎn)就是 一個(gè)方法中仰迁,前半段基本都是條件檢查甸昏,真正執(zhí)行的代碼一般都在最后。

這里的關(guān)鍵方法就是: startActivityUncheckedLocked

    final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;
        ...
        // 這里 省略的一段就是執(zhí)行 intent檢查徐许,看是否有目標(biāo)Actiivty響應(yīng) intet施蜜,或者啟動(dòng)Activity是否權(quán)限之類(lèi)的。

        doPendingActivityLaunchesLocked(false);

        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        if (err < 0) {
            // If someone asked to have the keyguard dismissed on the next
            // activity start, but we are not actually doing an activity
            // switch...  just dismiss the keyguard now, because we
            // probably want to see whatever is behind it.
            notifyActivityDrawnForKeyguard();
        }
        return err;
    }

執(zhí)行 startActivityUncheckedLocked


    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
        final Intent intent = r.intent;
        final int callingUid = r.launchedFromUid;

       ... 
           //這里前半段就是檢查當(dāng)前啟動(dòng)的activity棧是否存在雌隅,如果存在就直接將當(dāng)acitivyt進(jìn)行棧操作花墩。

        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                intent, r.getUriPermissionsLocked(), r.userId);

        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
        }
        if (newTask) {
            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
        }
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

4.5 ActivityStack.startActivityLocked

現(xiàn)在這里就是執(zhí)行棧操作,并且將棧跟Window進(jìn)行關(guān)聯(lián)澄步。

  final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
      ···
      //  上面省略的部分就是將當(dāng)前Stack和Window進(jìn)行關(guān)聯(lián)

        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

4.6 ActivityStackSupervisor .startSpecificActivityLocked

這里就是關(guān)鍵的一步了冰蘑, 如果當(dāng)前要啟動(dòng)的Activity進(jìn)程已經(jīng)起來(lái)了,那么就直接啟動(dòng)Activity

否則就調(diào)用AMS啟動(dòng)進(jìn)程村缸。


    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

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

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

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

4.7 AMS.startProcessLocked

這里主要三個(gè)任務(wù):

  1. 執(zhí)行檢查祠肥,看當(dāng)前包是否被凍結(jié)了,如果被凍結(jié)梯皿,那么就無(wú)法啟動(dòng)
  2. 啟動(dòng)Process
  3. 發(fā)送一個(gè)handler消息仇箱,用來(lái)定時(shí)檢查當(dāng)前Activity是否啟動(dòng)超時(shí)
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        long startTime = SystemClock.elapsedRealtime();
        
        try {
            try {
                if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) {
                    // This is caught below as if we had failed to fork zygote
                    throw new RuntimeException("Package " + app.info.packageName + " is frozen!");
                }
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            

            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, "startProcess: returned from zygote!");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

            if (app.isolated) {
                mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);
            }
            mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
            checkTime(startTime, "startProcess: done updating battery stats");

            
 
            synchronized (mPidsSelfLocked) {
                ProcessRecord oldApp;
                // If there is already an app occupying that pid that hasn't been cleaned up
                if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) {
                    // Clean up anything relating to this pid first
                    Slog.w(TAG, "Reusing pid " + startResult.pid
                            + " while app is still mapped to it");
                    cleanUpApplicationRecordLocked(oldApp, false, false, -1,
                            true /*replacingPid*/);
                }
                this.mPidsSelfLocked.put(startResult.pid, app);
                if (isActivityProcess) {
                    Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                    msg.obj = app;
                    mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                            ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
                }
            }
            checkTime(startTime, "startProcess: done updating pids map");
        } catch (RuntimeException e) {
            // XXX do better error recovery.
            app.setPid(0);
            mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
            if (app.isolated) {
                mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
            }
            Slog.e(TAG, "Failure starting process " + app.processName, e);
        }
    }

4.8 Process.start

這里就是第二次跨進(jìn)程調(diào)用了 ,但是這里這一次跨進(jìn)程通信用的就是Socket东羹,并不是Binder了剂桥。

SystemServer 進(jìn)程 ----> Zygote 進(jìn)程

Process.start方法可以說(shuō)是一個(gè)關(guān)鍵的步驟 這里就是通過(guò)Process 來(lái)用 Socket 跟Zygote進(jìn)程進(jìn)行通信, 通過(guò)socket命令属提,來(lái)執(zhí)行進(jìn)程的Fork权逗。

這里就可以看到包括SystemServer進(jìn)程美尸,Android系統(tǒng)中所有的進(jìn)程都是 zygote進(jìn)程孵化而來(lái), 這也就是 zygote 名字準(zhǔn)確性的體現(xiàn)斟薇。

這里涉及到Zygote進(jìn)程fork 進(jìn)程师坎,以及Socket通信就不在往下了,感興趣的可以繼續(xù)堪滨,下面列出幾個(gè)相關(guān)類(lèi):

ZygoteInit胯陋, LocalSocket,LocalSocketImpl

值得一提的是 在Linux中所有事件都是通過(guò)文件描述符來(lái)傳遞的, 因此Socket 其實(shí)也是基于文件描述符的袱箱。

4.9 ActivityThread啟動(dòng)

當(dāng)Zygote接受Socket命令遏乔,fork一個(gè)進(jìn)程之后,就走到 ActivityThread.main()方法 這里具體的 從4.8 ——> 4.9的更具體的細(xì)節(jié)我還沒(méi)搞懂发笔。

  public static void main(String[] args) {
        
        Environment.initForCurrentUser(); //這里也是執(zhí)行關(guān)鍵的一步盟萨,就是給當(dāng)前應(yīng)用創(chuàng)建 文件用戶操作文件夾

      

        AndroidKeyStoreProvider.install();

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

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();  //準(zhǔn)備主線程 也就是Actiivty運(yùn)行的looper

        ActivityThread thread = new ActivityThread();
        thread.attach(false); //這里也是一個(gè)關(guān)鍵地方  這里一次 IApplicationThread綁定

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

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

ActivityThread.attach()

在Attach方法中,也進(jìn)行了一些關(guān)鍵處理筐咧,

  1. 將ApplicationThread 作為一個(gè) Server注冊(cè)到AMS中鸯旁,這樣 AMS就可以和當(dāng)前應(yīng)用進(jìn)行通信了
  2. RuntimeInit.setApplicationObject 這一句也是關(guān)鍵代碼噪矛,這里就涉及到 APPCrash的處理了
  3. 添加GC 回調(diào)量蕊,出現(xiàn)內(nèi)存不足時(shí)回收內(nèi)存
  4. 向ViewRootImpl中注冊(cè) Configchange的回調(diào)
   private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {  //這里又是一次跨進(jìn)程調(diào)用了
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            // 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) {
                        }
                    }
                }
            });
        } else {
            
        }

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

4.10 AMS.attachApplication

到這里障斋,目標(biāo)APP的進(jìn)程已經(jīng)起來(lái)了价匠,然后APP又會(huì)反過(guò)來(lái)將自己的Server注冊(cè)到AMS中,

這樣AMS就可以繼續(xù)執(zhí)行我們最初的目標(biāo)筒捺,StartActivity缩滨。

   private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) { 
        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;
        }
 
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); // 之前有發(fā)送進(jìn)程啟動(dòng)超時(shí)的檢查消息势就,這里已經(jīng)啟動(dòng)成功,所以進(jìn)行移除

        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; //進(jìn)行contentProvider的 解析APP中的ContentProvider
        if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
        }
 

      
        try {
          
           
            ProfilerInfo profilerInfo = profileFile == null ? null
                    : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
            //這里也是一個(gè)關(guān)鍵步驟脉漏,又進(jìn)行了一次跨進(jìn)程Binder調(diào)用苞冯, 將事件回調(diào)給APp進(jìn)程,進(jìn)行APPlicaiton創(chuàng)建
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    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) {
            
            return false;
        }

 
        mPersistentStartingProcesses.remove(app);
        
        mProcessesOnHold.remove(app);

      
        // See if the top visible activity is waiting to run in this process...
       //繼續(xù)我們未完成的事業(yè)侧巨,去啟動(dòng)Actiivty舅锄。
        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...
         //繼續(xù)我們未完成的事業(yè),去啟動(dòng)Service
        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...
       //  繼續(xù)我們未完成的事業(yè)司忱,去進(jìn)行廣播接收
        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);
            ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
            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;
    }

4.11 AMS 事件回調(diào)給Application

  1. 先看bindApplication //這里進(jìn)行了一次跨進(jìn)程皇忿, 然后跨線程調(diào)用

    AMS --> Applicaiton 跨進(jìn)程

    Applicaton binder線程 ----> ActivityThread 線程

    
      private void handleBindApplication(AppBindData data) {
            
      
           //設(shè)置時(shí)區(qū)
            final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
         
             // 創(chuàng)建 Instrumentation
            if (data.instrumentationName != null) {
                InstrumentationInfo ii = null;
                try {
                    ii = appContext.getPackageManager().
                        getInstrumentationInfo(data.instrumentationName, 0);
                } catch (PackageManager.NameNotFoundException e) {
                }
                if (ii == null) {
                    throw new RuntimeException(
                        "Unable to find instrumentation info for: "
                        + data.instrumentationName);
                }
    
                mInstrumentationPackageName = ii.packageName;
                mInstrumentationAppDir = ii.sourceDir;
                mInstrumentationSplitAppDirs = ii.splitSourceDirs;
                mInstrumentationLibDir = ii.nativeLibraryDir;
                mInstrumentedAppDir = data.info.getAppDir();
                mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
                mInstrumentedLibDir = data.info.getLibDir();
    
                ApplicationInfo instrApp = new ApplicationInfo();
                instrApp.packageName = ii.packageName;
                instrApp.sourceDir = ii.sourceDir;
                instrApp.publicSourceDir = ii.publicSourceDir;
                instrApp.splitSourceDirs = ii.splitSourceDirs;
                instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
                instrApp.dataDir = ii.dataDir;
                instrApp.nativeLibraryDir = ii.nativeLibraryDir;
                LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true, false);
                
                //創(chuàng)建ContextImpl
                ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    
                try {
                    java.lang.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);
                }
    
                mInstrumentation.init(this, instrContext, appContext,
                       new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
                       data.instrumentationUiAutomationConnection);
     
    
            } else {
                mInstrumentation = new Instrumentation();
            }
    
          // 這里 如果設(shè)置了標(biāo)志位,大內(nèi)存應(yīng)用坦仍,進(jìn)行一次清理
            if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
                dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
            } else {
                
                dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
            }
          // 創(chuàng)建Application
            try {
                Application app = data.info.makeApplication(data.restrictedBackupMode, null);
                mInitialApplication = app;
                if (!data.restrictedBackupMode) {
                    List<ProviderInfo> providers = data.providers;
                    if (providers != null) {
                        //創(chuàng)建ContentProvider對(duì)象
                        installContentProviders(app, providers);
                        mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                    }
                }
    
               
                try {
                    mInstrumentation.onCreate(data.instrumentationArgs);
                }
                
     //這里 通過(guò)Instrumentation 去調(diào)用Application的onCreate方法鳍烁,可以看道Contentprovider先于Application onCreate調(diào)用調(diào)用
                try {
                    mInstrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                   
                }
            } finally {
                StrictMode.setThreadPolicy(savedPolicy);
            }
        }
    
  1. 然后看 performLaunchActivity,這里performLaunch 其實(shí)也是一次跨進(jìn)程調(diào)用繁扎,ActivityThread已經(jīng)創(chuàng)建 ActivityStackSuperversior 通過(guò)持有的 ActivityThread對(duì)象幔荒,跨進(jìn)程調(diào)用一次,將調(diào)用 ActiivtyThread.handleLaunchActivity

    AMS在跨進(jìn)程調(diào)用,使當(dāng)前進(jìn)程Application創(chuàng)建之后铺峭,墓怀,就回到我們之前的目的了,啟動(dòng)一個(gè)Activity卫键。

```java
  if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
```
  1. 重新回到 ActivityStackSupervisor

    遍歷Display傀履, 然后選出display中的Stack, 選中Stack如果沒(méi)有要啟動(dòng)的Activity莉炉,那么就重新進(jìn)入Activity創(chuàng)建流程

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

    這里又是一次跨進(jìn)程調(diào)用钓账, 使用當(dāng)前綁定的ApplicationThread來(lái)主動(dòng)啟動(dòng)Activity,之后就進(jìn)入我們的Activity啟動(dòng)流程了絮宁。

      final boolean realStartActivityLocked(ActivityRecord r,
                ProcessRecord app, boolean andResume, boolean checkConfig)
                throws RemoteException {
            final ActivityStack stack = task.stack;
            try {
                if (app.thread == null) {
                    throw new RemoteException();
                }
                List<ResultInfo> results = null;
                List<ReferrerIntent> newIntents = null; 
    
                if (andResume) {
                    app.hasShownUi = true;
                    app.pendingUiClean = true;
                }
                app.forceProcessStateUpTo(mService.mTopProcessState);
                //這里就用綁定的ApplicationThread對(duì)象來(lái)進(jìn)行跨進(jìn)程調(diào)用
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                        new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                        newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo); 
            } catch (RemoteException e) {
                if (r.launchFailed) { 
                    mService.appDiedLocked(app);
                    stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                            "2nd-crash", false);
                    return false;
                } 
                app.activities.remove(r);
                throw e;
            }
    
            
    
         
       
    
            return true;
        }
    

接下來(lái)的流程就是執(zhí)行Actiivty的創(chuàng)建梆暮,執(zhí)行生命周期了。 我們之后接著分析绍昂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啦粹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子窘游,更是在濱河造成了極大的恐慌唠椭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忍饰,死亡現(xiàn)場(chǎng)離奇詭異贪嫂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)艾蓝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)力崇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人赢织,你說(shuō)我怎么就攤上這事亮靴。” “怎么了于置?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵茧吊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我俱两,道長(zhǎng)饱狂,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任宪彩,我火速辦了婚禮休讳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尿孔。我一直安慰自己俊柔,他們只是感情好筹麸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著雏婶,像睡著了一般物赶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上留晚,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天酵紫,我揣著相機(jī)與錄音,去河邊找鬼错维。 笑死奖地,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赋焕。 我是一名探鬼主播参歹,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼隆判!你這毒婦竟也來(lái)了犬庇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侨嘀,失蹤者是張志新(化名)和其女友劉穎臭挽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體飒炎,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埋哟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年笆豁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了郎汪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闯狱,死狀恐怖煞赢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哄孤,我是刑警寧澤照筑,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瘦陈,受9級(jí)特大地震影響凝危,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晨逝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一蛾默、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捉貌,春花似錦支鸡、人聲如沸冬念。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)急前。三九已至,卻和暖如春瀑构,著一層夾襖步出監(jiān)牢的瞬間裆针,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工寺晌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留据块,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓折剃,卻偏偏與公主長(zhǎng)得像另假,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子怕犁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355