当前位置: 首页 > news >正文

Android系统Launcher启动流程学习(三)Launcher启动流程

Launcher 启动

系统启动的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,并作为这些安装程序的启动入口,这个应用程序就是Launcher。Launcher就是Android的桌面,主要作用就两点:

  1. 作为Android系统的启动器,用于启动应用程序
  2. 作为为Android的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件。

时序图

上面得知SystemServer 进程启动中会启动很多其他的服务,其中一个就是 ActivityManagerService,在 startOtherServices 中会调用 AMS 的 systemReady() 方法将 Lanuncher 启动起来
位置:frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices() {
//...
mActivityManagerService.systemReady(() -> {		//在startOtherService()方法中
            Slog.i(TAG, "Making services ready");
            traceBeginAndSlog("StartActivityManagerReadyPhase");
            mSystemServiceManager.startBootPhase(
                    SystemService.PHASE_ACTIVITY_MANAGER_READY);
            traceEnd();
            traceBeginAndSlog("StartObservingNativeCrashes");
            try {
                mActivityManagerService.startObservingNativeCrashes();
            } catch (Throwable e) {
                reportWtf("observing native crashes", e);
            }
            traceEnd();

            //...
        }, BOOT_TIMINGS_TRACE_LOG);

位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
        traceLog.traceBegin("PhaseActivityManagerReady");
        //...

        synchronized (this) {
            //...
            startHomeActivityLocked(currentUserId, "systemReady");
            //...
            //调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLock方法
            mStackSupervisor.resumeFocusedStackTopActivityLocked();
            mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
            //...
        }
    }

resumeFocusedStackTopActivityLocked

位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!readyToResume()) {
            return false;
        }

        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);	//从这里调用ActivityStack.java的函数
        }

        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.isState(RESUMED)) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }

        return false;
    }

位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

    @GuardedBy("mService")
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);	//使用函数

            // When resuming the top activity, it may be necessary to pause the top activity (for
            // example, returning to the lock screen. We suppress the normal pause logic in
            // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
            // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
            // to ensure any necessary pause logic occurs. In the case where the Activity will be
            // shown regardless of the lock screen, the call to
            // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }

        return result;
    }

    @GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }

        // Find the next top-most activity to resume in this stack that is not finishing and is
        // focusable. If it is not focusable, we will fall into the case below to resume the
        // top activity in the next focusable task.
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

        final boolean hasRunningActivity = next != null;

        // TODO: Maybe this entire condition can get removed?
        if (hasRunningActivity && !isAttached()) {
            return false;
        }

        mStackSupervisor.cancelInitializingActivities();

        // Remember how we'll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        if (!hasRunningActivity) {
            // There are no activities left in the stack, let's look somewhere else. 如果没有TopActivity运行
            return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
        }
		//...
    }

    private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
            ActivityOptions options, String reason) {
        if (adjustFocusToNextFocusableStack(reason)) {
            // Try to move focus to the next visible stack with a running activity if this
            // stack is not covering the entire screen or is on a secondary display (with no home
            // stack).
            return mStackSupervisor.resumeFocusedStackTopActivityLocked(
                    mStackSupervisor.getFocusedStack(), prev, null);
        }

        // Let's just start up the Launcher...
        ActivityOptions.abort(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        // Only resume home if on home display
        return isOnHomeDisplay() &&
                mStackSupervisor.resumeHomeStackTask(prev, reason);
    }

位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

	boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }

        mHomeStack.moveHomeStackTaskToTop();
        ActivityRecord r = getHomeActivity();
        final String myReason = reason + " resumeHomeStackTask";

        // Only resume home activity if isn't finishing.
        if (r != null && !r.finishing) {
            moveFocusableActivityStackToFrontLocked(r, myReason);
            return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
        }
        return mService.startHomeActivityLocked(mCurrentUser, myReason);	//这里调用了AMS的startHomeActivityLocked
    }

startHomeActivityLocked

在 AMS 中的 systemReady() 方法中执行 startHomeActivityLocked()方法,传入当前用户ID

    boolean startHomeActivityLocked(int userId, String reason) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // mFactoryTest为FactoryTest.FACTORY_TEST_LOW_LEVEL(低工厂模式)并且mTopAction等于null时,直接返回null
            // We are running in factory test mode, but unable to find
            // the factory test app, so just sit around displaying the
            // error message and don't try to start anything.
            return false;
        }

        Intent intent = getHomeIntent();		//获取到要启动的HomeActivity的intent对象
        //通过PackageManager去获取对应符合的Activity
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            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) {
            	//添加FLAG_ACTIVITY_NEW_TASK启动参数,开启新栈
                intent.setFlags(intent.getFlags() | 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;
                mActivityStartController.startHomeActivity(intent, aInfo, myReason);
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }

    Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);		//mTopAction默认为INTENT.ACTION_MAIN
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);	//添加CATEGORY_HOME的category标志
        }
        return intent;
    }

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

//位置:"./frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java"
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
        mSupervisor.moveHomeStackTaskToTop(reason);
		//调用obtainStarter()方法获取到一个ActivityStarter对象
        mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
                .setOutActivity(tmpOutRecord)
                .setCallingUid(0)
                .setActivityInfo(aInfo)
                .execute();
        mLastHomeActivityStartRecord = tmpOutRecord[0];
        if (mSupervisor.inResumeTopActivity) {
            // If we are in resume section already, home activity will be initialized, but not
            // resumed (to avoid recursive resume) and will stay that way until something pokes it
            // again. We need to schedule another resume.
            mSupervisor.scheduleResumeTopActivities();
        }
    }

    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);		//工厂模式创建ActivityStarter对象
    }

//位置"frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java"
	int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {		//mayWait默认为false
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent);
            } else {
            	//执行startActivity()进入Activity的启动流程
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent);
            }
        } finally {
            onExecutionComplete();
        }
    }

Launcher本身就是一个系统APP,用于显示桌面等,LauncherApp启动之后会执行其生命周期方法初始化桌面布局,至此,Launcher就启动完成了,用户进入到界面,整个Android系统也启动起来

Laucher应用程序图标显示过程

Launcher是一个桌面应用程序,先从Launcher的onCreate方法入手:
位置:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
		//...
        LauncherAppState app = LauncherAppState.getInstance(this);	//“获取LauncherAppState的实例”
        mOldConfig = new Configuration(getResources().getConfiguration());
        mModel = app.setLauncher(this);	//将Launcher对象传入
        initDeviceProfile(app.getInvariantDeviceProfile());

		//...
        if (!mModel.startLoader(currentScreen)) {		//调用LauncherModel的startLoader
            if (!internalStateHandled) {
                // If we are not binding synchronously, show a fade in animation when
                // the first page bind completes.
                mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
            }
        } else {
            // Pages bound synchronously.
            mWorkspace.setCurrentPage(currentScreen);

            setWorkspaceLoading(true);
        }

		//...
    }

位置: packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java


    LauncherModel setLauncher(Launcher launcher) {
        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
        mModel.initialize(launcher);		//调用LauncherModel的initialize方法
        return mModel;
    }

位置:packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java

    public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            Preconditions.assertUIThread();
            mCallbacks = new WeakReference<>(callbacks);	//封装成了弱引用对象
        }
    }


	//创建了具有消息循环的线程HandlerThread对象
    @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");		
    static {
        sWorkerThread.start();
    }
    //创建了Handler,并且传入HadlerThread的Looper,作用是向HandlerThread发送消息
    @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());


    public boolean startLoader(int synchronousBindPage) {
        // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
        InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
        synchronized (mLock) {
            // Don't bother to start the thread if we know it's not going to do anything
            if (mCallbacks != null && mCallbacks.get() != null) {
                final Callbacks oldCallbacks = mCallbacks.get();
                // Clear any pending bind-runnables from the synchronized load process.
                mUiExecutor.execute(oldCallbacks::clearPendingBinds);

                // If there is already one running, tell it to stop.
                stopLoader();
                //这里初始化会post一下
                LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
                        mBgAllAppsList, synchronousBindPage, mCallbacks);
                if (mModelLoaded && !mIsLoaderTaskRunning) {
                    // Divide the set of loaded items into those that we are binding synchronously,
                    // and everything else that is to be bound normally (asynchronously).
                    // 加载和绑定工作区信息
                    loaderResults.bindWorkspace();
                    // For now, continue posting the binding of AllApps as there are other
                    // issues that arise from that.
                    loaderResults.bindAllApps();	//加载系统已经安装的应用程序信息
                    loaderResults.bindDeepShortcuts();
                    loaderResults.bindWidgets();
                    return true;
                } else {
                    startLoaderForResults(loaderResults);
                }
            }
        }
        return false;
    }

位置:packages/apps/Launcher3/src/com/android/launcher3/model/LoaderResults.java

	public void bindAllApps() {
        // shallow copy
        @SuppressWarnings("unchecked")
        final ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();

        Runnable r = new Runnable() {
            public void run() {
                Callbacks callbacks = mCallbacks.get();		//这个mCallbacks是指向Launcher的
                if (callbacks != null) {
                    callbacks.bindAllApplications(list);	//调用bindAllApplications
                }
            }
        };
        mUiExecutor.execute(r);
    }

位置: packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

    public void bindAllApplications(ArrayList<AppInfo> apps) {
        mAppsView.getAppsStore().setApps(apps);		//调用mAppsView对象的setApps方法,并将包含应用信息的列表apps传进去

        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.bindAllApplications(apps);
        }
    }

位置:packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsRecyclerView.java

	public void setApps(AlphabeticalAppsList apps, boolean usingTabs) {
        mApps = apps;	//将包含应用信息的列表apps设置给mApps,这个mApps是AlphabeticalAppsList类型的对象
        mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
    }

接着查看AllAppsContainerView的onFinishInflate方法如下所示:
位置:packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsContainerView.java

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

        // This is a focus listener that proxies focus from a view into the list view.  This is to
        // work around the search box from getting first focus and showing the cursor.
        setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus && getActiveRecyclerView() != null) {
                getActiveRecyclerView().requestFocus();
            }
        });

        mHeader = findViewById(R.id.all_apps_header);
        rebindAdapters(mUsingTabs, true /* force */);

        mSearchContainer = findViewById(R.id.search_container_all_apps);
        mSearchUiManager = (SearchUiManager) mSearchContainer;
        mSearchUiManager.initialize(this);		//这里更新adapater
    }


位置:packages/apps/Launcher3/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java

    @Override
    public void initialize(AllAppsContainerView appsView) {
        mApps = appsView.getApps();
        mAppsView = appsView;
        mSearchBarController.initialize(
                new DefaultAppSearchAlgorithm(mApps.getApps()), this, mLauncher, this);
    }

相关文章:

  • Windows 10 ARM64平台MFC串口程序开发
  • 前端知识点---事件委托和机制-阻止冒泡机制-阻止默认行为机制(javascript)
  • JavaScript描述Object.create()方法的原理及作用,如何利用它创建一个具有指定原型的对象?
  • java: 无法访问org.springframework.web.bind.annotation.GetMapping
  • 正则表达式-笔记
  • Transformer的理解
  • 7.2 分治-快排:LeetCode 912. 排序数组
  • Debezium日常分享系列之:Debezium 3.1.0.CR1发布
  • 01STM32时钟树
  • 【redis】哨兵节点作用演示和重选主节点详细流程
  • Vue $bus被多次触发
  • Android 删除aar中的一个类 aar包冲突 aar类冲突 删除aar中的一个包
  • 【JavaScript】筑基期功法
  • Spring Boot 自定义 Starter 组件的技术指南
  • Vue简单的store模式
  • 【解决方法】VMware安装Ubuntu时安装窗口过小看不到继续按钮 | Ubuntu安装窗口过小看不到按钮
  • kotlin多平台(KMP)开发桌面运行及打包
  • UDP数据报套接字编程
  • 三维动态规划-LeetCode3418. 机器人可以获得的最大金币数
  • 3.26学习总结 做题
  • 国内站长做国外网站/企业员工培训课程内容
  • 青海企业网站开发定制/夸克搜索引擎入口
  • 做农业需关注什么网站/2022最新热点事件及点评
  • 超炫html5网站模板/提升关键词排名软件哪家好
  • 深圳做地铁的公司网站/宁海关键词优化怎么优化
  • 龙岗住房和建设局网站/平台宣传推广方案