App桌面圖標(biāo)顯示過(guò)程

《App的安裝過(guò)程》一篇我們分析了系統(tǒng)啟動(dòng)后,程序是如何被安裝到系統(tǒng)中的。安裝完成后朝墩,我們會(huì)看到桌面將顯示一個(gè)圖標(biāo),用于點(diǎn)擊啟動(dòng)App伟姐,這篇繼續(xù)分析圖標(biāo)的顯示過(guò)程收苏。

系統(tǒng)提供了一個(gè)Home程序,即Launcher愤兵,用來(lái)顯示系統(tǒng)中已經(jīng)安裝的程序鹿霸,它是有SystemServer進(jìn)程啟動(dòng)的,它也是第一個(gè)啟動(dòng)的應(yīng)用程序秆乳。

Launcher根據(jù)android.intent.action.MAIN和android.intent.category.LAUNCHER兩個(gè)條件懦鼠,將應(yīng)用入口封裝成一個(gè)快捷圖標(biāo),就能啟動(dòng)跳轉(zhuǎn)到對(duì)應(yīng)的程序屹堰。因此我們分析Launcher啟動(dòng)就能知道桌面圖標(biāo)的顯示過(guò)程肛冶,我們從SystemServer開(kāi)始看。

SystemServer的run方法會(huì)啟動(dòng)許多服務(wù)扯键,包含三類(lèi)BootstrapServices睦袖、CoreServices和OtherServices,Launcher的啟動(dòng)在OtherServices中荣刑。

 //運(yùn)行
    private void run() {
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            mProfilerSnapshotTimer = new Timer();
            mProfilerSnapshotTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }
      
        VMRuntime.getRuntime().clearGrowthLimit();

        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
 
        Build.ensureFingerprintProperty();
   
        Environment.setUserRequired(true);
 
        BinderInternal.disableBackgroundScheduling(true);

        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

        //加載services/core/jni/中的cpp代碼馅笙,初始化各種“本地服務(wù)”,看目錄下onload.cpp嘶摊,將java本地方法映射為c函數(shù)延蟹,java->c,
        System.loadLibrary("android_servers");
        //調(diào)用services/core/jni/com_android_server_SystemServer.cpp
        nativeInit();
     
        performPendingShutdown();

        createSystemContext();

        //創(chuàng)建SystemServiceManager叶堆,用來(lái)管理各種系統(tǒng)service
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

        try {
            //啟動(dòng)PMS阱飘,AMS等服務(wù)
            startBootstrapServices();
            // 啟動(dòng)LED、電池等核心服務(wù)
            startCoreServices();
            //啟動(dòng)IputManagerService等服務(wù)
            startOtherServices();
        } catch (Throwable ex) {         
            throw ex;
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

PMS,AMS等服務(wù)會(huì)優(yōu)先啟動(dòng)沥匈,其次是電池和LED等核心服務(wù)蔗喂,最后才是其他服務(wù),如WMS高帖、IMS等缰儿,Launcher也是在這個(gè)方法啟動(dòng)的。

    ......

    mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {

                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);

                try {
                    mActivityManagerService.startObservingNativeCrashes();
                } catch (Throwable e) {
                    reportWtf("observing native crashes", e);
                }
      ......

當(dāng)系統(tǒng)完成各種服務(wù)的注冊(cè)和啟動(dòng)后散址,將調(diào)用AMS的systemReady方法作為入口乖阵,讓AMS啟動(dòng)Launcher界面。

    public void systemReady(final Runnable goingCallback) {
        synchronized(this) {
              ......
            
            mBooting = true;
            //啟動(dòng)Launcher
            startHomeActivityLocked(mCurrentUserId);
            ......

        }
    }

    boolean startHomeActivityLocked(int userId) {
        //mFactoryTest描述系統(tǒng)的運(yùn)行模式预麸,分工廠非工廠瞪浸,工廠分低級(jí)和高級(jí)
        //mTopAction非工廠和高級(jí)工廠,mTopAction為Intent.ACTION_MAIN
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            return false;
        }
        //構(gòu)建跳轉(zhuǎn)Intent
        Intent intent = getHomeIntent();
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            //獲取app的進(jìn)程
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid, true);
            //加載首個(gè)Home程序Launcher時(shí)app為null
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                //到mStackSupervisor維護(hù)了所有的任務(wù)棧
                mStackSupervisor.startHomeActivity(intent, aInfo);
            }
        }

        return true;
    }

 Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
          //添加CATEGORY_HOME
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

系統(tǒng)運(yùn)行模式分兩類(lèi):工廠測(cè)試和非工廠測(cè)試吏祸。工廠測(cè)試分為:低級(jí)工廠測(cè)試和高級(jí)工廠測(cè)試对蒲。在非工廠測(cè)試和高級(jí)模式中,mTopAction為Intent .ACTION_MAIN,mTopData 和都為null贡翘。假設(shè)我們當(dāng)前運(yùn)行在非工廠測(cè)試模式下蹈矮,可以看到Category添加了一個(gè)Intent.CATEGORY_HOME,它配合Intent .ACTION_MAIN就構(gòu)成了我們要跳轉(zhuǎn)的Home程序的MainActivity鸣驱。我們看一眼AndroidManifest.xml文件泛鸟。

 <application
        android:name="com.android.launcher2.LauncherApplication"
        android:label="@string/application_name"
        android:icon="@mipmap/ic_launcher_home"
        android:hardwareAccelerated="true"
        android:largeHeap="@bool/config_largeHeap"
        android:supportsRtl="true">
        <activity
            android:name="com.android.launcher2.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:resumeWhilePausing="true"
            android:theme="@style/Theme"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="nosensor">
            <!--     入口過(guò)濾器       -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>

系統(tǒng)用一個(gè)ProcessRecord類(lèi)來(lái)描述一個(gè)應(yīng)用程序的進(jìn)程,由于系統(tǒng)還沒(méi)有啟動(dòng)過(guò)任何程序丐巫,getProcessRecordLocked首次將返回null谈况。mStackSupervisor是ActivityStackSupervisor類(lèi)型勺美,對(duì)任務(wù)棧管理器ActivityStack的管理递胧,ActivityStack則是對(duì)任務(wù)棧TaskRecord的管理,而每個(gè)Activity在任務(wù)棧中都使用ActivityRecord來(lái)進(jìn)行描述赡茸。我們通常所說(shuō)的Activity入棧缎脾,指的就是將ActivityRecord添加到對(duì)應(yīng)的TaskRecord中。

    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
        //驗(yàn)證Intent
        startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null,
                0, 0, 0, null, false, null, null, null);
    }
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 componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
            TaskRecord inTask) {

        int err = ActivityManager.START_SUCCESS;
    //ProcessRecord用來(lái)描述一個(gè)應(yīng)用程序的進(jìn)程占卧,并保存在AMS內(nèi)部
        ProcessRecord callerApp = null;
        if (caller != null) {
      //caller指向ApplicationThread遗菠,即讓ProcessRecord指向所運(yùn)行的應(yīng)用程序
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                //獲取進(jìn)程pid
                callingPid = callerApp.pid;
                //獲取進(jìn)程uid
                callingUid = callerApp.info.uid;
            } else {
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

       ......

        //創(chuàng)建ActivityRecord,用來(lái)描述啟動(dòng)入口的MainActivity
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, this, container, options);
        if (outActivity != null) {
            outActivity[0] = r;
        }
        final ActivityStack stack = getFocusedStack();
        if (voiceSession == null && (stack.mResumedActivity == null
                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                    realCallingPid, realCallingUid, "Activity start")) {
                PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
                mPendingActivityLaunches.add(pal);
                ActivityOptions.abort(options);
                return ActivityManager.START_SWITCHES_CANCELED;
            }
        }
        if (mService.mDidAppSwitch) {
            mService.mAppSwitchesAllowedTime = 0;
        } else {
            mService.mDidAppSwitch = true;
        }

        doPendingActivityLaunchesLocked(false);

        //驗(yàn)證完成华蜒,開(kāi)始啟動(dòng)模式判斷
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        if (err < 0) {
            notifyActivityDrawnForKeyguard();
        }
        return err;
    }

根據(jù)callingPid和callingUid 構(gòu)建了一個(gè)ActivityRecord辙纬,前面說(shuō)過(guò),它用來(lái)描述Launcher程序的ManActivity在棧中的信息叭喜。注意倒數(shù)第三個(gè)參數(shù)doResume為true贺拣。

 final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {

         ActivityStack targetStack;
        intent.setFlags(launchFlags);

        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || launchSingleInstance || launchSingleTask) {

            if (inTask == null && r.resultTo == null) {
           
                ActivityRecord intentActivity = !launchSingleInstance ?
                        findTaskLocked(r) : findActivityLocked(intent, r.info);
                if (intentActivity != null) {
                    if (isLockTaskModeViolation(intentActivity.task)) {
                        showLockTaskToast();
                        Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                        return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
                    }
                    if (r.task == null) {
                        r.task = intentActivity.task;
                    }
                    //獲取棧管理器
                    targetStack = intentActivity.task.stack;
                    targetStack.mLastPausedActivity = null;
          ......

        targetStack.mLastPausedActivity = null;
        //獲取Activity棧開(kāi)啟
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            mService.setFocusedActivityLocked(r);
        }
        return ActivityManager.START_SUCCESS;
    }

targetStack為ActivityStack類(lèi)型 ,它管理了多個(gè)任務(wù)棧TaskRecord 。

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
          ......
        //執(zhí)行resume
        if (doResume) {
            //resume頂部的Activity
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

又回到了大管家ActivityStackSupervisor的resumeTopActivitiesLocked方法譬涡。

  boolean resumeTopActivitiesLocked() {
        return resumeTopActivitiesLocked(null, null, null);
    }

  boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = getFocusedStack();
        }
       
        boolean result = false;
        if (isFrontStack(targetStack)) {
            //再次調(diào)用了targetStack的resumeTopActivityLocked闪幽,此時(shí)mResumedActivity==null了
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

這里從新回到TargetStack,是因?yàn)楸仨毰袛喈?dāng)前棧頂是否有未pause的Activity涡匀,如果有的話先暫停舊的Activity盯腌,才會(huì)resume新的Activity。

final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
        if (!mService.mBooting && !mService.mBooted) {!
            return false;
        }
        ActivityRecord parent = mActivityContainer.mParentActivity;
        if ((parent != null && parent.state != ActivityState.RESUMED) ||
                !mActivityContainer.isAttachedLocked()) {
            return false;
        }
        cancelInitializingActivities();

        //獲取棧頂不是處于結(jié)束狀態(tài)的Activity,next即指向了MainAcivity
        ActivityRecord next = topRunningActivityLocked(null);

        .....
      //先執(zhí)行當(dāng)前Activity的Pause陨瘩,再執(zhí)行新的resume
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        if (mResumedActivity != null) {
            //執(zhí)行pause腕够,即Launcher進(jìn)入Pause,然后再啟動(dòng)next舌劳,即MainActivity
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
           
        }

        ......
        //開(kāi)啟新的Activity
            mStackSupervisor.startSpecificActivityLocked(next, true, true);

next表示我們正準(zhǔn)備啟動(dòng)的Activity燕少,mResumedActivity 表示將被關(guān)閉的Activity,如果mResumedActivity 不為null蒿囤,表示還沒(méi)有執(zhí)行pause客们,將先調(diào)用startPausingLocked來(lái)執(zhí)行。

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        //每個(gè)Activity都會(huì)記錄當(dāng)前的進(jìn)程名和用戶(hù)id材诽,如果這個(gè)進(jìn)程存在底挫,就通知AMS將這個(gè)Activity啟動(dòng)起來(lái)
        //不存在則根據(jù)進(jìn)程名和用戶(hù)id,創(chuàng)建新的進(jìn)程脸侥,再啟動(dòng)activity
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        r.task.stack.setLaunchTime(r);

        //進(jìn)程存在建邓,直接啟動(dòng)
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //啟動(dòng)新activity
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

        }
        //第一次點(diǎn)擊圖標(biāo),進(jìn)程不在睁枕,新建
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

根據(jù)進(jìn)程名和用戶(hù)id從AMS中獲取當(dāng)前的進(jìn)程官边,獲取成功返回一個(gè)ProcessRecord對(duì)象,它是對(duì)應(yīng)用程序進(jìn)程的描述外遇,如果存在注簿,則調(diào)用realStartActivityLocked開(kāi)啟新的Activity;如果不存在跳仿,將執(zhí)行startProcessLocked方法通知Zygote啟動(dòng)新進(jìn)程诡渴。我們先看AMS如何通知的。

  //生成新進(jìn)程
   final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {

        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

 final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        //先新建ProcessRecord菲语,保存進(jìn)程信息
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            checkTime(startTime, "startProcess: after getProcessRecord");
        } else {
            app = null;
        }
   
        if (app != null && app.pid > 0) {
            if (!knownToBeDead || app.thread == null) {
                app.addPackage(info.packageName, info.versionCode, mProcessStats);
                return app;
            }
            Process.killProcessGroup(app.info.uid, app.pid);
            handleAppDiedLocked(app, true, true);
            checkTime(startTime, "startProcess: done killing old proc");
        }

        String hostingNameStr = hostingName != null
                ? hostingName.flattenToShortString() : null;

        if (!isolated) {
            if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    return null;
                }
            } else {
                mProcessCrashTimes.remove(info.processName, info.uid);
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                            UserHandle.getUserId(info.uid), info.uid,
                            info.processName);
                    mBadProcesses.remove(info.processName, info.uid);
                    if (app != null) {
                        app.bad = false;
                    }
                }
            }
        }

        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            app.crashHandler = crashHandler;
            if (app == null) {
                return null;
            }
            mProcessNames.put(processName, app.uid, app);
            if (isolated) {
                mIsolatedProcesses.put(app.uid, app);
            }
        } else {
            //添加包名妄辩、版本號(hào)和進(jìn)程狀態(tài)
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
        }

        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            if (!mProcessesOnHold.contains(app)) {
                mProcessesOnHold.add(app);
            }
            return app;
        }
        //通知Zygote創(chuàng)建一個(gè)新的進(jìn)程
        startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        return (app.pid != 0) ? app : null;
    }

ProcessRecord 保存了包名,版本號(hào)等信息山上,傳遞給startProcessLocked的另一個(gè)重載方法眼耀。

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            ......

            //告訴Zygote子進(jìn)程孵化ActivityThread進(jìn)程后,調(diào)用main方法
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
     
            //開(kāi)啟進(jìn)程
            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);

Process是用來(lái)管理系統(tǒng)應(yīng)用程序進(jìn)程的工具佩憾,靜態(tài)方法start哮伟,將使用Socket通訊連接上Zygote潭辈,讓其孵化新的進(jìn)程ActivityThread,并運(yùn)行ActivityThread的main方法澈吨。

 public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
            //使用ArrayList保存uid等數(shù)據(jù)
            ArrayList<String> argsForZygote = new ArrayList<String>();
            argsForZygote.add("--runtime-init");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
                argsForZygote.add("--enable-jni-logging");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
                argsForZygote.add("--enable-safemode");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
                argsForZygote.add("--enable-debugger");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
                argsForZygote.add("--enable-checkjni");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                argsForZygote.add("--enable-assert");
            }
            if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
                argsForZygote.add("--mount-external-multiuser");
            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
                argsForZygote.add("--mount-external-multiuser-all");
            }
            argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

            if (gids != null && gids.length > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append("--setgroups=");

                int sz = gids.length;
                for (int i = 0; i < sz; i++) {
                    if (i != 0) {
                        sb.append(',');
                    }
                    sb.append(gids[i]);
                }

                argsForZygote.add(sb.toString());
            }

            if (niceName != null) {
                argsForZygote.add("--nice-name=" + niceName);
            }

            if (seInfo != null) {
                argsForZygote.add("--seinfo=" + seInfo);
            }

            if (instructionSet != null) {
                argsForZygote.add("--instruction-set=" + instructionSet);
            }

            if (appDataDir != null) {
                argsForZygote.add("--app-data-dir=" + appDataDir);
            }

            argsForZygote.add(processClass);

            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }
            //連接Zygote并發(fā)送請(qǐng)求取得結(jié)果
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

openZygoteSocketIfNeeded用于連接Zygote把敢,并返回連接狀態(tài)。zygoteSendArgsAndGetResult用于發(fā)送請(qǐng)求并取得響應(yīng)數(shù)據(jù)谅辣。

 private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
              //連接Zygote
                primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
        }

        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }
        //嘗試第二次連接
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
            secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
            }
        }

        if (secondaryZygoteState.matches(abi)) {
            return secondaryZygoteState;
        }

        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }

為了和Zygote進(jìn)行Socket通訊修赞,這里做了兩次連接嘗試,讓后將連接狀態(tài)返回桑阶。

private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;
            //向Zygote發(fā)送請(qǐng)求數(shù)據(jù)
            writer.write(Integer.toString(args.size()));
            writer.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);
                writer.newLine();
            }
            writer.flush();
        
            //構(gòu)建ProcessStartResult
            ProcessStartResult result = new ProcessStartResult();
            //從流數(shù)據(jù)讀取pid
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

如果進(jìn)程創(chuàng)建成功柏副,pid進(jìn)程id將不小于0,否則說(shuō)明創(chuàng)建失敗了蚣录。關(guān)于Zygote是如何接受請(qǐng)求的割择,我們留到新的篇章分析。
我們回過(guò)頭來(lái)分析realStartActivityLocked方法萎河。

 final boolean realStartActivityLocked(ActivityRecord r,ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
        //凍結(jié)未啟動(dòng)的其他Activity
        r.startFreezingScreenLocked(app, 0);
        if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
        //向WindowManager設(shè)置Token荔泳,標(biāo)識(shí)當(dāng)前App要位于前臺(tái)顯示
        mWindowManager.setAppVisibility(r.appToken, true);
        //搜索啟動(dòng)較慢的App的信息
        r.startLaunchTickingLocked();
        //檢查配置信息
        if (checkConfig) {
            Configuration config = mWindowManager.updateOrientationFromAppTokens(
                    mService.mConfiguration,
                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
            mService.updateConfigurationLocked(config, r, false, false);
        }
        r.app = app;//記錄了當(dāng)前Activity在哪個(gè)進(jìn)程上運(yùn)行的
        app.waitingToKill = null;
        r.launchCount++;
        r.lastLaunchTime = SystemClock.uptimeMillis();
        if (localLOGV) Slog.v(TAG, "Launching: " + r);
        int idx = app.activities.indexOf(r);

        if (idx < 0) {
            app.activities.add(r);//將Activity將入到進(jìn)程維護(hù)的activity列表中
        }
        mService.updateLruProcessLocked(app, true, null);
        mService.updateOomAdjLocked();

        final ActivityStack stack = r.task.stack;
        try {
            if (app.thread == null) {
                throw new RemoteException();
            }
            List<ResultInfo> results = null;
            List<Intent> newIntents = null;
            //是否調(diào)用onResume,上面?zhèn)魅肓藅ure
            if (andResume) {
                results = r.results;
                newIntents = r.newIntents;
            }

            if (andResume) {
                EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
                        r.userId, System.identityHashCode(r),
                        r.task.taskId, r.shortComponentName);
            }
            //是否桌面Activity虐杯,如果是玛歌,添加到Activity棧底部
            if (r.isHomeActivity() && r.isNotResolverActivity()) {
                // Home process is the root process of the task.
                mService.mHomeProcess = r.task.mActivities.get(0).app;
            }
            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
            r.sleeping = false;
            r.forceNewConfig = false;
            mService.showAskCompatModeDialogLocked(r);
            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
            String profileFile = null;
            ParcelFileDescriptor profileFd = null;
            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                if (mService.mProfileProc == null || mService.mProfileProc == app) {
                    mService.mProfileProc = app;
                    profileFile = mService.mProfileFile;
                    profileFd = mService.mProfileFd;
                }
            }
            app.hasShownUi = true;
            app.pendingUiClean = true;
            if (profileFd != null) {
                try {
                    profileFd = profileFd.dup();
                } catch (IOException e) {
                    if (profileFd != null) {
                        try {
                            profileFd.close();
                        } catch (IOException o) {
                        }
                        profileFd = null;
                    }
                }
            }

            ProfilerInfo profilerInfo = profileFile != null
                    ? new ProfilerInfo(profileFile, profileFd, mService.mSamplingInterval,
                    mService.mAutoStopProfiler) : null;
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);

            //app為ProcessRecord,封裝了進(jìn)程的信息
            //app.thread為IApplicationThread擎椰,用于ApplicationThread和AMS之間的通信
            //經(jīng)過(guò)上面的賦值操作支子,回到ActivityThread的內(nèi)部類(lèi)ApplicationThread調(diào)用scheduleLaunchActivity,設(shè)置所有參數(shù)达舒,再調(diào)用Handler發(fā)送消息調(diào)用handleLaunchActivity
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                    results, newIntents, !andResume, mService.isNextTransitionForward(),
                    profilerInfo);

        .....

thread為IApplicationThread類(lèi)型值朋,當(dāng)新的進(jìn)程被創(chuàng)建,主線程ActivityThread被構(gòu)建巩搏,它的成員變量ApplicationThread就被初始化昨登,它繼承自ApplicationThreadNative,本質(zhì)是一個(gè)Binder塔猾,用于跨進(jìn)程和AMS進(jìn)行通訊篙骡。

 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();

    final SparseArray<ForegroundToken> mForegroundProcesses = new SparseArray<ForegroundToken>();

    final ArrayList<ProcessRecord> mProcessesOnHold = new ArrayList<ProcessRecord>();
 
    final ArrayList<ProcessRecord> mPersistentStartingProcesses = new ArrayList<ProcessRecord>();

    final ArrayList<ProcessRecord> mRemovedProcesses = new ArrayList<ProcessRecord>();

    final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();

    int mLruProcessActivityStart = 0;

    int mLruProcessServiceStart = 0;

    final ArrayList<ProcessRecord> mProcessesToGc = new ArrayList<ProcessRecord>();

    final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();

AMS使用了許多個(gè)列表稽坤,來(lái)保存不同狀態(tài)下進(jìn)程的ProcessRecord丈甸,ProcessRecord的成員變量thread則持有ApplicationThread的遠(yuǎn)程代理接口IApplicationThread ,因此AMS和ActivityThread能進(jìn)行通訊尿褪。

final class ProcessRecord {
  ......
    IApplicationThread thread; 

scheduleLaunchActivity方法用于正式啟動(dòng)Activity并顯示睦擂,我們將在《Activity的啟動(dòng)過(guò)程》《Activity渲染過(guò)程》中詳細(xì)分析。

我們知道啟動(dòng)Home的LaunerActivity成功后杖玲,最終會(huì)執(zhí)行到onCreate方法顿仇。

public class Launcher extends BaseDraggingActivity implements LauncherExterns,
        LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{
     
     ......

    @Thunk AllAppsContainerView mAppsView; //所有App圖標(biāo)的容器
    AllAppsTransitionController mAllAppsController;//對(duì)圖標(biāo)的控制器
   
    ......

  //管理Launcher界面的中的數(shù)據(jù),統(tǒng)合管理App,AppWidget等的讀取
    private LauncherModel mModel;
    private ModelWriter mModelWriter;
    private IconCache mIconCache;
    private LauncherAccessibilityDelegate mAccessibilityDelegate;

    ......

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       
        TraceHelper.beginSection("Launcher-onCreate");

        super.onCreate(savedInstanceState);
        TraceHelper.partitionSection("Launcher-onCreate", "super call");

        LauncherAppState app = LauncherAppState.getInstance(this);
        mOldConfig = new Configuration(getResources().getConfiguration());
        //初始化整個(gè)界面的Model
        mModel = app.setLauncher(this);

        initDeviceProfile(app.getInvariantDeviceProfile());

        mSharedPrefs = Utilities.getPrefs(this);
        mIconCache = app.getIconCache();
        mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);

        mDragController = new DragController(this);
        //初始化控制器
        mAllAppsController = new AllAppsTransitionController(this);
        mStateManager = new LauncherStateManager(this);
        UiFactory.onCreate(this);

        mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);

        mAppWidgetHost = new LauncherAppWidgetHost(this);
        mAppWidgetHost.startListening();

        mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null);
        //初始化圖標(biāo)容器
        setupViews();
        ......

        //加載安裝的應(yīng)用程序
        if (!mModel.startLoader(currentScreen)) {
            if (!internalStateHandled) {
                mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
            }
        } else {
            mWorkspace.setCurrentPage(currentScreen);
            setWorkspaceLoading(true);
        }

        setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
        //顯示桌面布局
        setContentView(mLauncherView);
        ......

    }

這里有幾個(gè)很關(guān)鍵的方法臼闻,LauncherAppState用于保存Launcher程序的狀態(tài)鸿吆,它使用setLauncher方法初始化LauncherModel ,


public class LauncherAppState {

    public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";

    private static LauncherAppState INSTANCE;

    private final Context mContext;
    private final LauncherModel mModel;
  .....

    private LauncherAppState(Context context) {
        if (getLocalProvider(context) == null) {
            throw new RuntimeException(
                    "Initializing LauncherAppState in the absence of LauncherProvider");
        }
        Log.v(Launcher.TAG, "LauncherAppState initiated");
        Preconditions.assertUIThread();
        mContext = context;

        mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
        mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
        mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
        //構(gòu)造LauncherModel
        mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
  
        ......
  }

 LauncherModel setLauncher(Launcher launcher) {
        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
      //初始化LauncherModel
        mModel.initialize(launcher);
        return mModel;
    }

看初始化LauncherModel的方法initialize述呐。

public class LauncherModel extends BroadcastReceiver
        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {

  @Thunk WeakReference<Callbacks> mCallbacks;

public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            Preconditions.assertUIThread();
          //LauncherModel可調(diào)用Launcher實(shí)現(xiàn)的方法
            mCallbacks = new WeakReference<>(callbacks);
        }
    }

 public interface Callbacks {
        public void rebindModel();
        public int getCurrentWorkspaceScreen();
        public void clearPendingBinds();
        public void startBinding();
        public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons);
        public void bindScreens(ArrayList<Long> orderedScreenIds);
        public void finishFirstPageBind(ViewOnDrawExecutor executor);
        public void finishBindingItems();
        public void bindAllApplications(ArrayList<AppInfo> apps);
        public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps);
        public void bindAppsAdded(ArrayList<Long> newScreens,
                                  ArrayList<ItemInfo> addNotAnimated,
                                  ArrayList<ItemInfo> addAnimated);
        public void bindPromiseAppProgressUpdated(PromiseAppInfo app);
        public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated, UserHandle user);
        public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
        public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
        public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher);
        public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos);
        public void bindAllWidgets(ArrayList<WidgetListRowEntry> widgets);
        public void onPageBoundSynchronously(int page);
        public void executeOnNextDraw(ViewOnDrawExecutor executor);
        public void bindDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMap);
    }

LauncherModel的初始化是為了構(gòu)建Callbacks接口惩淳,而這個(gè)接口被Launcher實(shí)現(xiàn)了。

public class Launcher extends BaseDraggingActivity implements LauncherExterns,
        LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{

AllAppsController服務(wù)于AllAppsContainerView乓搬,幫助處理所有App的拖拽等事件思犁。我們會(huì)在setupViews方法里看到他們的關(guān)聯(lián)。

private void setupViews() {
        mDragLayer = findViewById(R.id.drag_layer);
        mFocusHandler = mDragLayer.getFocusIndicatorHelper();
        mWorkspace = mDragLayer.findViewById(R.id.workspace);
        mWorkspace.initParentViews(mDragLayer);
        mOverviewPanel = findViewById(R.id.overview_panel);
        mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
        mHotseat = findViewById(R.id.hotseat);
        mHotseatSearchBox = findViewById(R.id.search_container_hotseat);

        mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

        mDragLayer.setup(mDragController, mWorkspace);
        UiFactory.setOnTouchControllersChangedListener(this, mDragLayer::recreateControllers);

        mWorkspace.setup(mDragController);
       
        mWorkspace.lockWallpaperToDefaultPage();
        mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);
        mDragController.addDragListener(mWorkspace);
        mDropTargetBar = mDragLayer.findViewById(R.id.drop_target_bar);

        //獲取圖標(biāo)容器
        mAppsView = findViewById(R.id.apps_view);

        mDragController.setMoveTarget(mWorkspace);
        mDropTargetBar.setup(mDragController);

        //通過(guò)mAllAppsController控制圖標(biāo)
        mAllAppsController.setupViews(mAppsView);
    }

執(zhí)行一系列的findViewById操作进肯,找到存儲(chǔ)應(yīng)用圖標(biāo)的容器激蹲,將它傳遞給AllAppsController。

 public void setupViews(AllAppsContainerView appsView) {
        mAppsView = appsView;
        mScrimView = mLauncher.findViewById(R.id.scrim_view);
    }

mAppsView 是AllAppsContainerView類(lèi)型的江掩,它是所有應(yīng)用程序的視圖容器学辱,先看其構(gòu)造方法。

public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mLauncher = Launcher.getLauncher(context);
        mLauncher.addOnDeviceProfileChangeListener(this);

        mSearchQueryBuilder = new SpannableStringBuilder();
        Selection.setSelection(mSearchQueryBuilder, 0);

        mAH = new AdapterHolder[2];
        mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
        mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);

        mNavBarScrimPaint = new Paint();
        mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));

        //界面更新會(huì)回調(diào)到onAppsUpdated
        mAllAppsStore.addUpdateListener(this::onAppsUpdated);

        addSpringView(R.id.all_apps_header);
        addSpringView(R.id.apps_list_view);
        addSpringView(R.id.all_apps_tabs_view_pager);
    }

this::onAppsUpdated為OnUpdateListener類(lèi)型的接口环形,當(dāng)應(yīng)用程序的信息被成功裝載到AllAppsStore后项郊,就會(huì)刷新界面,回調(diào)onAppsUpdated方法斟赚。這個(gè)方法稍后分析着降,我們先來(lái)看應(yīng)用程序信息如何被裝載的∞志回到Launcher的OnCreate任洞,LauncherModel調(diào)用了startLoader方法。

 public boolean startLoader(int synchronousBindPage) {
        InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
        synchronized (mLock) {

            if (mCallbacks != null && mCallbacks.get() != null) {
                final Callbacks oldCallbacks = mCallbacks.get();
                mUiExecutor.execute(oldCallbacks::clearPendingBinds);
                stopLoader();
                LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
                        mBgAllAppsList, synchronousBindPage, mCallbacks);

                //加載過(guò)進(jìn)入綁定
                if (mModelLoaded && !mIsLoaderTaskRunning)
                    loaderResults.bindWorkspace();
                    loaderResults.bindAllApps();
                    loaderResults.bindDeepShortcuts();
                    loaderResults.bindWidgets();
                    return true;
                } else {
                 //未加載
                    startLoaderForResults(loaderResults);
                }
            }
        }
        return false;
    }

首次進(jìn)入為未加載狀態(tài)发侵,因?yàn)檠b載app是一個(gè)很耗時(shí)的操作交掏,系統(tǒng)將loaderResults放到LoaderTask這個(gè)Runnable中執(zhí)行。

 public void startLoaderForResults(LoaderResults results) {
        synchronized (mLock) {
            stopLoader();
            //構(gòu)建Runnable
            mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
            啟動(dòng)run方法
            runOnWorkerThread(mLoaderTask);
        }
    }

跟進(jìn)LoaderTask的run方法中刃鳄。

  public void run() {
        synchronized (this) {
            if (mStopped) {
                return;
            }
        }

        TraceHelper.beginSection(TAG);
        try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
            ......
          TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
            //加載app信息
            loadAllApps();
          TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
            verifyNotStopped();
            //綁定數(shù)據(jù)
            mResults.bindAllApps();
    ......
  }

    private void loadAllApps() {
        final List<UserHandle> profiles = mUserManager.getUserProfiles();

        mBgAllAppsList.clear();
        for (UserHandle user : profiles) {
        
            final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
            if (apps == null || apps.isEmpty()) {
                return;
            }
            boolean quietMode = mUserManager.isQuietModeEnabled(user);
            for (int i = 0; i < apps.size(); i++) {
                LauncherActivityInfo app = apps.get(i);
                //保存app信息
                mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
            }
        }

        if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
            for (PackageInstaller.SessionInfo info :
                    mPackageInstaller.getAllVerifiedSessions()) {
                mBgAllAppsList.addPromiseApp(mApp.getContext(),
                        PackageInstallerCompat.PackageInstallInfo.fromInstallingState(info));
            }
        }

        mBgAllAppsList.added = new ArrayList<>();
    }

所有應(yīng)用程序信息已經(jīng)加載完成盅弛,保存到mBgAllAppsList中。

public void bindAllApps() {
        @SuppressWarnings("unchecked")
        final ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
        Runnable r = new Runnable() {
            public void run() {
                Callbacks callbacks = mCallbacks.get();
                //回調(diào)Launcher的bindAllApplications方法
                if (callbacks != null) {
                    callbacks.bindAllApplications(list);
                }
            }
        };
        mUiExecutor.execute(r);
    }

這里注意到叔锐,mBgAllAppsList把應(yīng)用程序的數(shù)據(jù)封裝成AppInfo類(lèi)型的挪鹏,圖標(biāo)的點(diǎn)擊事件會(huì)根據(jù)這個(gè)類(lèi)型進(jìn)行判斷∮淅樱看到bindAllApps方法讨盒,前面分析過(guò),Launcher實(shí)現(xiàn)了Callbacks 步责,這里mBgAllAppsList將數(shù)據(jù)克隆了一份返顺,通過(guò)bindAllApplications方法禀苦,傳遞給了Launcher。


public void bindAllApplications(ArrayList<AppInfo> apps) {
        //更新數(shù)據(jù)到AllAppsStore中
        mAppsView.getAppsStore().setApps(apps);
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.bindAllApplications(apps);
        }
    }

AllAppsContainerView中有一個(gè)AllAppsStore類(lèi)型的成員變量遂鹊,它用來(lái)對(duì)桌面應(yīng)用程序信息進(jìn)行管理振乏,并且當(dāng)數(shù)據(jù)更新時(shí)通知AllAppsContainerView容器進(jìn)行刷新。這里的setApps便是向AllAppsStore中更新數(shù)據(jù)的關(guān)鍵方法秉扑。

public class AllAppsStore {

    private PackageUserKey mTempKey = new PackageUserKey(null, null);
    private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>();
    private final List<OnUpdateListener> mUpdateListeners = new ArrayList<>();
    private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>();
    private boolean mDeferUpdates = false;
    private boolean mUpdatePending = false;

    //獲取應(yīng)用程序信息集合
    public Collection<AppInfo> getApps() {
        return mComponentToAppMap.values();
    }

    public void setApps(List<AppInfo> apps) {
        mComponentToAppMap.clear();
        //設(shè)置當(dāng)前的應(yīng)用程序數(shù)據(jù)
        addOrUpdateApps(apps);
    }

   public void addOrUpdateApps(List<AppInfo> apps) {
        //將應(yīng)用程序信息添加到Map集合中
        for (AppInfo app : apps) {
            mComponentToAppMap.put(app.toComponentKey(), app);
        }
        //刷新界面
        notifyUpdate();
    }

    private void notifyUpdate() {
        if (mDeferUpdates) {
            mUpdatePending = true;
            return;
        }
        int count = mUpdateListeners.size();
     //通知AllAppsContainerView刷新界面
        for (int i = 0; i < count; i++) {
            mUpdateListeners.get(i).onAppsUpdated();
        }
    }

  ......
}

AllAppsStore 將數(shù)據(jù)保存到成員變量mComponentToAppMap中昆码,緊接著我們看到,前面的AllAppsContainerView構(gòu)造方法設(shè)置的監(jiān)聽(tīng)邻储,onAppsUpdated就在這里被回調(diào)了赋咽。稍后我們會(huì)看到,桌面圖標(biāo)也是通過(guò)RecyCleView進(jìn)行展示的吨娜,那么現(xiàn)在數(shù)據(jù)已經(jīng)準(zhǔn)備完成脓匿,就差setAdapter了。

    private void onAppsUpdated() {
        if (FeatureFlags.ALL_APPS_TABS_ENABLED) {
            boolean hasWorkApps = false;
            for (AppInfo app : mAllAppsStore.getApps()) {
                if (mWorkMatcher.matches(app, null)) {
                    hasWorkApps = true;
                    break;
                }
            }
            //把圖標(biāo)數(shù)據(jù)等宦赠,綁定到adapter中
            rebindAdapters(hasWorkApps);
        }
    }

 private void rebindAdapters(boolean showTabs) {
        rebindAdapters(showTabs, false /* force */);
    }

 private void rebindAdapters(boolean showTabs, boolean force) {
        if (showTabs == mUsingTabs && !force) {
            return;
        }
        replaceRVContainer(showTabs);
        mUsingTabs = showTabs;

        mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
        mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.WORK].recyclerView);
        //綁定數(shù)據(jù)setup
        if (mUsingTabs) {
            mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
            mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkMatcher);
            onTabChanged(mViewPager.getNextPage());
        } else {
            mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
            mAH[AdapterHolder.WORK].recyclerView = null;
        }
        setupHeader();

        mAllAppsStore.registerIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
        mAllAppsStore.registerIconContainer(mAH[AdapterHolder.WORK].recyclerView);
    }

AdapterHolder是AllAppsContainerView的內(nèi)部類(lèi)陪毡,我們進(jìn)入看setup綁定數(shù)據(jù)。

 public class AdapterHolder {
        public static final int MAIN = 0;
        public static final int WORK = 1;

        public final AllAppsGridAdapter adapter;
        final LinearLayoutManager layoutManager;
        final AlphabeticalAppsList appsList;
        final Rect padding = new Rect();
        AllAppsRecyclerView recyclerView;
        boolean verticalFadingEdge;

        AdapterHolder(boolean isWork) {
            appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore, isWork);
            adapter = new AllAppsGridAdapter(mLauncher, appsList);
            appsList.setAdapter(adapter);
            layoutManager = adapter.getLayoutManager();
        }

        //設(shè)置adapter
        void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
            appsList.updateItemFilter(matcher);
            recyclerView = (AllAppsRecyclerView) rv;
            recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
            recyclerView.setApps(appsList, mUsingTabs);
            recyclerView.setLayoutManager(layoutManager);
          //設(shè)置adapter
            recyclerView.setAdapter(adapter);
            recyclerView.setHasFixedSize(true);
            recyclerView.setItemAnimator(null);
            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
            recyclerView.addItemDecoration(focusedItemDecorator);
            adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
            applyVerticalFadingEdgeEnabled(verticalFadingEdge);
            applyPadding();
        }

在setup中我們看到setAdapter方法了勾扭,桌面的圖標(biāo)到這里就全部顯示出來(lái)毡琉。顯然,它必須給每個(gè)圖標(biāo)設(shè)置點(diǎn)擊事件妙色,所以我們接著看AllAppsGridAdapter 的onCreateViewHolder方法桅滋。

 @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case VIEW_TYPE_ICON:
              //圖標(biāo)控件
                BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
                        R.layout.all_apps_icon, parent, false);
              //桌面圖標(biāo)點(diǎn)擊事件
                icon.setOnClickListener(ItemClickHandler.INSTANCE);
                icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS);
                icon.setLongPressTimeout(ViewConfiguration.getLongPressTimeout());
                icon.setOnFocusChangeListener(mIconFocusListener);
                icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
                return new ViewHolder(icon);
            ......
        }
    }

viewType有許多類(lèi)型,桌面圖標(biāo)為VIEW_TYPE_ICON類(lèi)型身辨,點(diǎn)擊事件使用ItemClickHandler將OnClickListener給包裝起來(lái)丐谋。

public class ItemClickHandler {

    public static final OnClickListener INSTANCE = ItemClickHandler::onClick;

    private static void onClick(View v) {
        if (v.getWindowToken() == null) {
            return;
        }

        Launcher launcher = Launcher.getLauncher(v.getContext());
        if (!launcher.getWorkspace().isFinishedSwitchingState()) {
            return;
        }

        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            onClickAppShortcut(v, (ShortcutInfo) tag, launcher);
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                onClickFolderIcon(v);
            }
        //桌面圖標(biāo)為AppInfo類(lèi)型數(shù)據(jù)
        } else if (tag instanceof AppInfo) {
            startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
        } else if (tag instanceof LauncherAppWidgetInfo) {
            if (v instanceof PendingAppWidgetHostView) {
                onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
            }
        }
    }

//開(kāi)始Activity的啟動(dòng)
    private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
        Intent intent;
        if (item instanceof PromiseAppInfo) {
            PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
            intent = promiseAppInfo.getMarketIntent(launcher);
        } else {
            intent = item.getIntent();
        }
        if (intent == null) {
            throw new IllegalArgumentException("Input must have a valid intent");
        }
        if (item instanceof ShortcutInfo) {
            ShortcutInfo si = (ShortcutInfo) item;
            if (si.hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI)
                    && intent.getAction() == Intent.ACTION_VIEW) {
                intent = new Intent(intent);
                intent.setPackage(null);
            }
        }
        //開(kāi)始Activity的啟動(dòng)
        launcher.startActivitySafely(v, intent, item);
    }
}

在前面提到過(guò),桌面圖標(biāo)的應(yīng)用程序信息都用AppInfo來(lái)描述煌珊,它包含應(yīng)用根Activity入口的顧慮條件号俐。因此調(diào)用startAppShortcutOrInfoActivity方法,最后再次回到Launcher啟動(dòng)Activity定庵。

    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        //調(diào)用父類(lèi)啟動(dòng)Activity
        boolean success = super.startActivitySafely(v, intent, item);
        if (success && v instanceof BubbleTextView) {
            BubbleTextView btv = (BubbleTextView) v;
            btv.setStayPressed(true);
            setOnResumeCallback(btv);
        }
        return success;
    }

Launcher的父類(lèi)是BaseDraggingActivity吏饿。

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
      boolean useLaunchAnimation = (v != null) &&
                !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
          Bundle optsBundle = useLaunchAnimation
                ? getActivityLaunchOptionsAsBundle(v)
                : null;
         ......

                //開(kāi)啟應(yīng)用的主入口的activity
                startActivity(intent, optsBundle);

            } else {
                LauncherAppsCompat.getInstance(this).startActivityForProfile(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            getUserEventDispatcher().logAppLaunch(v, intent);
            return true;
        } catch (ActivityNotFoundException|SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
        }
        return false;
    }

看到了我們非常熟悉的代碼startActivity了,它將啟動(dòng)應(yīng)用的根Activity蔬浙,這個(gè)方法位于Activity.java中猪落。它的具體調(diào)用流程會(huì)在《Activity的啟動(dòng)過(guò)程》一篇中繼續(xù)分析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末敛滋,一起剝皮案震驚了整個(gè)濱河市许布,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绎晃,老刑警劉巖蜜唾,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異庶艾,居然都是意外死亡袁余,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)咱揍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颖榜,“玉大人,你說(shuō)我怎么就攤上這事煤裙⊙谕辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵硼砰,是天一觀的道長(zhǎng)且蓬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)题翰,這世上最難降的妖魔是什么恶阴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮豹障,結(jié)果婚禮上冯事,老公的妹妹穿的比我還像新娘。我一直安慰自己血公,他們只是感情好昵仅,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著累魔,像睡著了一般岩饼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上薛夜,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天籍茧,我揣著相機(jī)與錄音,去河邊找鬼梯澜。 笑死寞冯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晚伙。 我是一名探鬼主播吮龄,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼咆疗!你這毒婦竟也來(lái)了漓帚?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤午磁,失蹤者是張志新(化名)和其女友劉穎尝抖,沒(méi)想到半個(gè)月后毡们,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昧辽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年衙熔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搅荞。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡红氯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咕痛,到底是詐尸還是另有隱情痢甘,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布茉贡,位于F島的核電站塞栅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏块仆。R本人自食惡果不足惜构蹬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悔据。 院中可真熱鬧庄敛,春花似錦、人聲如沸科汗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)头滔。三九已至怖亭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坤检,已是汗流浹背兴猩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留早歇,地道東北人倾芝。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像箭跳,于是被迫代替她去往敵國(guó)和親晨另。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容