提醒每个阶段的关键步骤 Launcher进程的启动到用户界面的出现

  • 电脑网络维修
  • 2024-11-15

Launcher启动器

Launcher(启动器、桌面) 是 Android 操作系统上用于展现运行图标、搜查运行、控制桌面快捷模式以及口头其余与设备主屏幕关系义务的用户界面。设备的主屏幕规划和外观是用户与设备交互的关键模式。

Launcher特点:

Launcher进程启动流程

SystemServer是Android系统中的一个外围进程,担任启动和初始化各种系统服务。

在SystemServer的启动环节中,会调用其余服务,如PackageManagerService(PMS)和ActivityManagerService(AMS)的初始化方法。

public final class SystemServer {private void run() {...startBootstrapServices();startOtherServices();...}private void startBootstrapServices() {...mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);...}private void startOtherServices() {...mActivityManagerService.systemReady(() -> {}, BOOT_TIMINGS_TRACE_LOG);}}

在SystemServer启动的时刻,口头startOtherServices()方法中调用了AMS的systemReady()方法,经过该方法来启动Launcher。

// Tag for timing measurement of main thread.private static final String SYSTEM_SERVER_TIMING_TAG = "SystemServerTiming";private static final TimingsTraceLog BOOT_TIMINGS_TRACE_LOG= new TimingsTraceLog(SYSTEM_SERVER_TIMING_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);private void startOtherServices() {...mActivityManagerService.systemReady(() -> {Slog.i(TAG, "Making services ready");traceBeginAndSlog("StartActivityManagerReadyPhase");mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);...}, BOOT_TIMINGS_TRACE_LOG);}

PMS服务会成功系统中运行程序的装置和控制上班。

PMS会扫描/data/app目录,加载曾经装置的运行程序消息。

AMS是Android系统中担任控制运行程序生命周期和优惠(Activity)形态的服务。

在AMS的初始化环节中,会注册各种系统广播接纳器,包含与Launcher启动关系的广播。

4.「Launcher运行程序的注册」:

Launcher运行程序是一个不凡的系统运行,它在AndroidManifest.xml文件中性能了特定的Intent Filter,以便系统能够识别并启动它。

通常,Launcher运行程序的Action被设置为Intent.ACTION_MAIN,而Category被设置为Intent.CATEGORY_HOME。

5.「SystemReady阶段」:

当系统成功初始化并预备好启动桌面时,AMS会调用其systemReady()方法。

在systemReady()方法中,AMS会审核系统能否预备好启动Launcher,并调用关系方法来启动。

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {...synchronized (this) {...startHomeActivityLocked(currentUserId, "systemReady");...}...}

在startHomeActivityLocked()方法中,经过getHomeIntent()方法失掉到要启动的HomeActivity的intent对象,mTopAction默以为INTENT.ACTION_MAIN,并参与CATEGORY_HOME的category标记。经过PackageManager去失掉对应合乎的Activity,失掉对应的ActivityInfo,并失掉对应的进程记载,此时对应的进程还没启动,为intent参与FLAG_ACTIVITY_NEW_TASK启动参数开启新栈,随后调用ActivityStartController类的startHomeActivity()方法去口头启动。

boolean startHomeActivityLocked(int userId, String reason) {...Intent intent = getHomeIntent();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) {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);}}...return true;}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;}

AMS启动Launcher进程。

该方法会创立一个新的进程(假设Launcher尚未运转)来启动Launcher运行程序。

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {mSupervisor.moveHomeStackTaskToTop(reason);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();}}int execute() {try {// TODO(b/64750076): Look into passing request directly to these methods to allow// for transactional diffs and preprocessing.if (mRequest.mayWait) {return startActivityMayWait(mRequest.caller, mRequest.callingUid,...);} else {return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, ...);}} finally {onExecutionComplete();}}

Launcher进程启动后,会向PMS恳求已装置运行程序的消息,并将这些消息展如今桌面上。

用户可以经过点击桌面上的运行程序图标来启动相应的运行程序。

@TargetApi(23)public InvariantDeviceProfile(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();DisplayMetrics dm = new DisplayMetrics();display.getMetrics(dm);...ArrayList<InvariantDeviceProfile> closestProfiles = findClosestDeviceProfiles(minWidthDps, minHeightDps, getPredefinedDeviceProfiles(context));...}ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles(Context context) {ArrayList<InvariantDeviceProfile> profiles = new ArrayList<>();try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {final int depth = parser.getDepth();int type;while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {if ((type == XmlPullParser.START_TAG) && "profile".equals(parser.getName())) {TypedArray a = context.obtainStyledAttributes(Xml.asAttributeSet(parser), R.styleable.InvariantDeviceProfile);int numRows = a.getInt(R.styleable.InvariantDeviceProfile_numRows, 0);int numColumns = a.getInt(R.styleable.InvariantDeviceProfile_numColumns, 0);float iconSize = a.getFloat(R.styleable.InvariantDeviceProfile_iconSize, 0);profiles.add(new InvariantDeviceProfile(a.getString(R.styleable.InvariantDeviceProfile_name),a.getFloat(R.styleable.InvariantDeviceProfile_minWidthDps, 0),a.getFloat(R.styleable.InvariantDeviceProfile_minHeightDps, 0),numRows,numColumns,a.getInt(R.styleable.InvariantDeviceProfile_numFolderRows, numRows),a.getInt(R.styleable.InvariantDeviceProfile_numFolderColumns, numColumns),iconSize,a.getFloat(R.styleable.InvariantDeviceProfile_landscapeIconSize, iconSize),a.getFloat(R.styleable.InvariantDeviceProfile_iconTextSize, 0),a.getInt(R.styleable.InvariantDeviceProfile_numHotseatIcons, numColumns),a.getResourceId(R.styleable.InvariantDeviceProfile_defaultLayoutId, 0),a.getResourceId(R.styleable.InvariantDeviceProfile_demoModeLayoutId, 0)));a.recycle();}}} catch (IOException|XmlPullParserException e) {throw new RuntimeException(e);}return profiles;}

InvariantDeviceProfile对象关键是存储App的基本色能消息,例如App图标的尺寸大小,文字大小,每个上班空间或文件夹能显示多少App等。

在LauncherModel的startLoader()方法中,新建了一个LoaderResults对象,经过startLoaderForResults()方法创立出一个LoaderTask的Runnable义务。

public boolean startLoader(int synchronousBindPage) {...synchronized (mLock) {// Don't bother to start the thread if we know it's not going to do anythingif (mCallbacks != null && mCallbacks.get() != null) {...LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel, mBgAllAppsList, synchronousBindPage, mCallbacks);if (mModelLoaded && !mIsLoaderTaskRunning) {...return true;} else {startLoaderForResults(loaderResults);}}}return false;}public void startLoaderForResults(LoaderResults results) {synchronized (mLock) {stopLoader();mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);runOnWorkerThread(mLoaderTask);}}private static void runOnWorkerThread(Runnable r) {if (sWorkerThread.getThreadId() == Process.myTid()) {r.run();} else {// If we are not on the worker thread, then post to the worker handlersWorker.post(r);}}

在LoaderTask的run()方法中,加载手机已装置的App的消息,查问数据库失掉已装置的App的关系消息,加载Launcher规划,并将数据转化为View,绑定到界面上,最终就可以看到桌面显示的宫格列表的桌面图标了。

public void run() {...try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {// 查问数据库整顿App消息,转化为View绑定到界面loadWorkspace();mResults.bindWorkspace();loadAllApps();mResults.bindAllApps();loadDeepShortcuts();mResults.bindDeepShortcuts();mBgDataModel.widgetsModel.update(mApp, null);mResults.bindWidgets();transaction.commit();} catch (CancellationException e) {// Loader stopped, ignoreTraceHelper.partitionSection(TAG, "Cancelled");}TraceHelper.endSection(TAG);}

随着Android系统的始终开展和降级,Launcher进程的启动流程也或者会出现相应的变动和提升。Android系统还支持多种启动Launcher的模式,如开机后智能启动、短按Home键启动以及意外解体后智能重启等。这些启动模式的成功流程也有所不同,但基本流程都与上述步骤相似。

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://duobeib.com/diannaowangluoweixiu/7430.html

猜你喜欢

热门标签

洗手盆如何疏浚梗塞 洗手盆为何梗塞 iPhone提价霸占4G市场等于原价8折 明码箱怎样设置明码锁 苏泊尔电饭锅保修多久 长城画龙G8253YN彩电输入指令画面变暗疑问检修 彩星彩电解除童锁方法大全 三星笔记本培修点上海 液晶显示器花屏培修视频 燃气热水器不热水要素 热水器不上班经常出现3种处置方法 无氟空调跟有氟空调有什么区别 norltz燃气热水器售后电话 大连站和大连北站哪个离周水子机场近 热水器显示屏亮显示温度不加热 铁猫牌保险箱高效开锁技巧 科技助力安保无忧 创维8R80 汽修 a1265和c3182是什么管 为什么电热水器不能即热 标致空调为什么不冷 神舟培修笔记本培修 dell1420内存更新 青岛自来水公司培修热线电话 包头美的洗衣机全国各市售后服务预定热线号码2024年修缮点降级 创维42k08rd更新 空调为什么运转异响 热水器为何会漏水 该如何处置 什么是可以自己处置的 重庆华帝售后电话 波轮洗衣机荡涤价格 鼎新热水器 留意了!不是水平疑问! 马桶产生了这5个现象 方便 极速 邢台空调移机电话上门服务 扬子空调缺点代码e4是什么疑问 宏基4736zG可以装置W11吗 奥克斯空调培修官方 为什么突然空调滴水很多 乐视s40air刷机包 未联络视的提高方向 官网培修 格力空调售后电话 皇明太阳能电话 看尚X55液晶电视进入工厂形式和软件更新方法 燃气热水器缺点代码

热门资讯

关注我们

微信公众号