启动launcher进程的过程

android源码学习目录

介绍

了解launcher的都知道他是Android系统启动的第一应用,也就是我们通常说的手机主界面,它也是异常普通的Android app.

1.SystemServer对launcher的启动

上文已经介绍过SystemServer对Android系统的各个服务进行了启动,当全部服务启动完成后,会进行launcher的启动,这样才能让用户见到手机的界面。

//systemServer的startOtherService函数内,
 
 mActivityManagerService.systemReady(() -> {
            Slog.i(TAG, "Making services ready");
            traceBeginAndSlog("StartActivityManagerReadyPhase");
            mSystemServiceManager.startBootPhase(
                    SystemService.PHASE_ACTIVITY_MANAGER_READY);
            traceEnd();

            ````

        }, BOOT_TIMINGS_TRACE_LOG);

这里是Android systemServer服务启动最后启动launcher的入口,它调用了ActivityManagerService的systemReady函数,在activitymanagerserver准备好之后,就启动launcher app,

// /framework/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
             ......

            mStackSupervisor.resumeFocusedStackTopActivityLocked(); //1 
            mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
            traceLog.traceEnd(); // ActivityManagerStartApps
            traceLog.traceEnd(); // PhaseActivityManagerReady
        }
    }

详细代码我们不需要了解,因为所要了解的知识太多,这里我们只了解个过程就可以了。重要的是注释1处的代码

// mStackSuperVisor为ActivityStackSupervisor.java
//   
 boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
}

boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);  
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);  //1
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }

代码会执行到注释1处,ActivityStack是Activity的堆栈,了解这个方法。

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        .....

        if (prevTask != null && prevTask.getStack() == this &&
                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
            if (prevTask == nextTask) {
                prevTask.setFrontOfTask();
            } else if (prevTask != topTask()) {
                // This task is going away but it was supposed to return to the home stack.
                // Now the task above it has to return to the home task instead.
                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            } else if (!isOnHomeDisplay()) {
                return false;
            } else if (!isHomeStack()){
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Launching home next");
                return isOnHomeDisplay() &&
                        mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");   //1
            }
        }

         ......

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

这个函数的代码执行重要在注释1处,resumeHomeStackTask函数,

 // /framework/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
        ....
        return mService.startHomeActivityLocked(mCurrentUser, myReason);
    }

这个函数调动了ActivityManagerService的startHomeActivityLocked函数,这个函数是launcher启动的关键函数。

    boolean startHomeActivityLocked(int userId, String reason) {
        ....

        Intent intent = getHomeIntent(); //1
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);  //2
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
          
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instr == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                // For ANR debugging to verify if the user activity is the one that actually
                // launched.
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
                mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);  //3
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }

这里代码就启动launcher的代码。分三部,构建intent,根据intent查找Activity信息,启动Activity。

  • 注释1处
    Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

这里mTopAction为String mTopAction = Intent.ACTION_MAIN,ACTION_MAIN为android.intent.action.MAIN,这里我们知道这个是launcher的重要标记,我们开发launcher的时候也是用的这个将APP作为一个launcher。后续的代码为intent增加了一些参数。

  • 代码注释2处:
// 在ActivityManagerService中
    private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
        ActivityInfo ai = null;
        ComponentName comp = intent.getComponent();
        try {
            if (comp != null) {
                // Factory test.
                ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); //从PackageManagerService中找到这个Activity
            } else {
                ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
                        intent,
                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                        flags, userId);

                if (info != null) {
                    ai = info.activityInfo;
                }
            }
        } catch (RemoteException e) {
            // ignore
        }

        return ai;
    }

上诉代码目的只有一个,根据intent从PackageManagerService中找到这个Activity,

  • 注释3处:
    mActivityStarter.startHomeActivityLocked, 就是启动这个Activity的方法,从这个函数之后,运行就和普通的Activity启动一样了,这里我们不进行详细介绍,后续会对 ActivityManagerService是怎样运行的进行详细介绍。
  • 到这里systemService利用ActivityManagerService对系统启动第一个应用launcher已经完成了。

2.Launcher的图标显示。

我们知道我们手机上launcher启动后,会将我们手机上安装的所有应用进行列表展示。这是怎么操作的呢,从前面文章的分析我们知道这个必定会和包管理服务PackageManagerService有关,我们现在查看launcher主要的Activity启动后只怎样查找使用所有APP的。
launcher启动的主Activity。

// /packages/apps/launcher3/AndroidManifest.xml
        
            
                
                
                
                
            
        

从上面的xml文件中可以看到"android.intent.action.MAIN注释的Activity为com.android.launcher3.Launcher,所以它就是launcher的第一个activity。

1.1 Launcher的onCreate方法

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        .....

        LauncherAppState app = LauncherAppState.getInstance(this);  // 1 创建launcherAppState

     ....

        mSharedPrefs = Utilities.getPrefs(this);
        mIsSafeModeEnabled = getPackageManager().isSafeMode();
        mModel = app.setLauncher(this);   // 2 设置LauncherAppState的Launcher
        mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout());
        mIconCache = app.getIconCache();
        ....

        mLauncherView = getLayoutInflater().inflate(R.layout.launcher, null);   // 3 加载布局文件

        setupViews();
        mDeviceProfile.layout(this, false /* notifyListeners */);
        mExtractedColors = new ExtractedColors();
        loadExtractedColorsAndColorItems();

        mPopupDataProvider = new PopupDataProvider(this);

        ((AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE))
                .addAccessibilityStateChangeListener(this);

        lockAllApps();

        restoreState(savedInstanceState);

        if (LauncherAppState.PROFILE_STARTUP) {
            Trace.endSection();
        }

        // We only load the page synchronously if the user rotates (or triggers a
        // configuration change) while launcher is in the foreground
        int currentScreen = PagedView.INVALID_RESTORE_PAGE;
        if (savedInstanceState != null) {
            currentScreen = savedInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN, currentScreen);
        }
        if (!mModel.startLoader(currentScreen)) {   //  4 开始加载APP信息
            // If we are not binding synchronously, show a fade in animation when
            // the first page bind completes.
            mDragLayer.setAlpha(0);
        } else {
            // Pages bound synchronously.
            mWorkspace.setCurrentPage(currentScreen);

            setWorkspaceLoading(true);
        }
        ....
    }
  • 注释1处:获取了LauncherAppState对象,并在注释2处将Laucher对象设置到了launcherAppState.

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


   public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            Preconditions.assertUIThread();
            // Remove any queued UI runnables
            mHandler.cancelAll();
            mCallbacks = new WeakReference<>(callbacks);
        }
    }

这里setLauncher就是将launcher类对象以弱引用方式放入mCallbacks, WeakReference就是弱引用。

  • 注释3处:加载了这个Activity的布局文件。
  • 注释4处:是很重要的一节,这里开始加载手机内所有APP的数据
// packages/apps/Launcher3/src/com/android/launcher3/LauncherModel
    public boolean startLoader(int synchronousBindPage) { 
        synchronized (mLock) {
            ....
            if (mCallbacks != null && mCallbacks.get() != null) {
                final Callbacks oldCallbacks = mCallbacks.get();
                // Clear any pending bind-runnables from the synchronized load process.
                runOnMainThread(new Runnable() {
                    public void run() {
                        oldCallbacks.clearPendingBinds(); //1清除原有的内容
                    }
                });

                // If there is already one running, tell it to stop.
                stopLoaderLocked();
                mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage); //构建LoaderTask
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
                        && mModelLoaded && !mIsLoaderTaskRunning) {
                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                    return true;
                } else {
                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                    sWorker.post(mLoaderTask); //2 执行LoaderTask, sWorker是一个handler。
                }
            }
        }
        return false;
    }
  • 注释1处进行了原有callback也就是launcher数据的清除
  • 注释2处进行了LoaderTask的构建,sWorker对loaderTask进行了执行。
packages/apps/Launcher3/src/com/android/launcher3/LauncherModel--LoaderTask run函数
 public void run() {
            synchronized (mLock) {
                if (mStopped) {
                    return;
                }
                mIsLoaderTaskRunning = true;
            }

            try {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
                // Set to false in bindWorkspace()
                mIsLoadingAndBindingWorkspace = true;
                loadWorkspace();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.2: bind workspace workspace");
                bindWorkspace(mPageToBindFirst);

                // Take a break
                if (DEBUG_LOADERS) Log.d(TAG, "step 1 completed, wait for idle");
                waitForIdle();
                verifyNotStopped();

                // second step
                if (DEBUG_LOADERS) Log.d(TAG, "step 2.1: loading all apps");
                loadAllApps();

                .....
            }
        }

上面函数每一步都有日志,翻译过来很好理解它做了什么,

  1. 加载和绑定工作区:Launcher是用工作区来显示系统安装的应用图标的,每个工作区都用来描述一个抽象桌面,它由N个桌面构成,每个桌面又分N个单元格。
  2. loadAllApps加载所有的APP
  private void loadAllApps() {
            ...
            mBgAllAppsList.clear();
            for (UserHandle user : profiles) {
                // Query for the set of apps
                final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
                final List apps = mLauncherApps.getActivityList(null, user); // 1获取所有APP的launcher-Activity信息
                ....
            mHandler.post(new Runnable() {
                public void run() {

                    final long bindTime = SystemClock.uptimeMillis();
                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                    if (callbacks != null) {
                        callbacks.bindAllApplications(added);  //2 绑定APP launcher信息。
                    } else {
                        Log.i(TAG, "not binding apps: no Launcher activity");
                    }
          .....
        }

  • 注释1处,获取所有APP的launcher Activity信息,因为每个APP,只要有界面就必定由一个launcher Activity。
  • 注释2处:将所有的APP信息绑定,对之前的分析我们知道callbacks是Launcher类,我们看看绑定了什么。
    public void bindAllApplications(final ArrayList apps) {
        ...

        if (mAppsView != null) {
            mAppsView.setApps(apps);   //1 将APP数据添加到mAppsVIew内,
        }
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.bindAllApplications(apps);
        }
    }

重要代码,mAppsView是AllAppsContainerView,位置为/packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsContainerView,
AllAppsContainerView中的mApps是AlphabeticalAppsList,设置给它保存了下来,这时候APP的数据就加载完成了 。

1.2 APP数据的展示。

在上一节我们在Launcher类的oncreate函数中了解到它对布局文件进行了解析,最后调用了setContentVIew为Activity进行了界面设置。

mLauncherView = getLayoutInflater().inflate(R.layout.launcher, null);
setContentView(mLauncherView);

这个加载布局中包含上文中提到的AllAppsContainerView,在看AllAppContainerVIew中的一个函数。

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

       ....

        // Load the all apps recycler view
        mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);
        mAppsRecyclerView.setApps(mApps);
        mAppsRecyclerView.setLayoutManager(mLayoutManager);
        mAppsRecyclerView.setAdapter(mAdapter);
        mAppsRecyclerView.setHasFixedSize(true);
        mAppsRecyclerView.addOnScrollListener(mElevationController);
        mAppsRecyclerView.setElevationController(mElevationController);

        FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mAppsRecyclerView);
        mAppsRecyclerView.addItemDecoration(focusedItemDecorator);
        mAppsRecyclerView.preMeasureViews(mAdapter);
        mAdapter.setIconFocusListener(focusedItemDecorator.getFocusListener());

        if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) {
            getRevealView().setVisibility(View.VISIBLE);
            getContentView().setVisibility(View.VISIBLE);
            getContentView().setBackground(null);
        }
    }

这个函数会在这个控件所在的xml被加载完成后触发, 这里的代码我们熟悉了,这就是对一个recyeleView进行的数据、adapter、layoutManager的设置,这里的mAppRecyclerView就是重写了RecyclerView, 用来展示所有已安装应用的图标等信息。

2 总结

到这里launcher已经启动并显示了所有的已安装的APP,这里我们可以认为Android系统的启动过程完全结束了。我的文章也对对Android整个系统分析完成了,但是这个分析的过程很粗略,很多代码和细节都没有写。想了解的可以跟着这个思路再细化这个Android系统启动的过程文章,欢迎投稿。

你可能感兴趣的:(启动launcher进程的过程)