//在systemServer的startOtherService函数中,
mActivityManagerService.systemReady(() -{
Slog.i(TAG, "准备服务");
traceBeginAndSlog("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
跟踪结束();
````
}, BOOT_TIMINGS_TRACE_LOG);这是Android系统服务器服务启动启动器的入口点。它调用ActivityManagerService的systemReady函数。 ActivityManagerServer 准备就绪后,启动器应用程序将启动。
///framework/base/services/core/java/com/android/server/am/ActivityManagerService.java
公共无效systemReady(最终可运行的goCallback,BootTimingsTraceLog跟踪日志){
.
mStackSupervisor.resumeFocusedStackTopActivityLocked(); //1
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
跟踪日志.traceEnd(); //ActivityManager启动应用程序
跟踪日志.traceEnd(); //PhaseActivityManager就绪
}
}我们不需要知道详细的代码,因为有太多的知识需要知道。这里我们只需要知道流程就可以了。重要的是注释1处的代码
//mStackSuperVisor 是ActivityStackSupervisor.java
//
布尔resumeFocusedStackTopActivityLocked() {
返回resumeFocusedStackTopActivityLocked(null, null, null);
}
布尔resumeFocusedStackTopActivityLocked(
ActivityStack targetStack、ActivityRecord 目标、ActivityOptions targetOptions) {
if (targetStack !=null isFocusedStack(targetStack)) {
返回targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
最终ActivityRecord r=mFocusedStack.topRunningActivityLocked();
if (r==null || r.state !=RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null); //1
} else if (r.state==RESUMED) {
//从MoveTaskToFront 操作启动任何延迟的应用程序转换。
mFocusedStack.executeAppTransition(targetOptions);
}
返回假;
}将执行注释1的代码。ActivityStack是Activity的堆栈。了解这个方法。
布尔resumeTopActivityUncheckedLocked(ActivityRecord prev,ActivityOptions选项){
……
if (prevTask !=null prevTask.getStack()==this
prevTask.isOverHomeStack() prev.finishing prev.frontOfTask) {
如果(DEBUG_STACK)mStackSupervisor.validateTopActivitiesLocked();
if (上一个任务==下一个任务) {
prevTask.setFrontOfTask();
} else if (prevTask !=topTask()) {
//该任务即将消失,但它应该返回到主堆栈。
//现在它上面的任务必须返回到主任务。
最终int taskNdx=mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
} else if (!isOnHomeDisplay()) {
返回假;
} else if (!isHomeStack()){
如果(DEBUG_STATES)Slog.d(TAG_STATES,
"resumeTopActivityLocked: 启动下一个主页");
返回isOnHomeDisplay()
mStackSupervisor.resumeHomeStackTask(prev, "prevFinished"); //1
}
}
.
如果(DEBUG_STACK)mStackSupervisor.validateTopActivitiesLocked();
返回真;
}该函数的代码执行在注释1中很重要,resumeHomeStackTask函数,
///framework/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
布尔resumeHomeStackTask(ActivityRecord prev,字符串原因){
.
返回mService.startHomeActivityLocked(mCurrentUser, myReason);
}该函数调动了ActivityManagerService的startHomeActivityLocked函数。该函数是启动器启动的关键函数。
boolean startHomeActivityLocked(int userId, String Reason) {
.
意图意图=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);
最终intsolvedUserId=UserHandle.getUserId(aInfo.applicationInfo.uid);
//用于ANR 调试以验证用户活动是否是实际活动
//启动。
最终字符串myReason=Reason + ":" + userId + ":" + returnedUserId;
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason); //3
}
} 别的{
Slog.wtf(TAG, "找不到主屏幕" + Intent, new Throwable());
}
返回真;
}此代码是启动启动器的代码。分为三部分,构建intent,根据intent找到Activity信息,启动Activity。
注1 Intent getHomeIntent() {
Intent意图=new Intent(mTopAction, mTopData !=null ? Uri.parse(mTopData) : null);
Intent.setComponent(mTopComponent);
Intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
如果(mFactoryTest!=FactoryTest.FACTORY_TEST_LOW_LEVEL){
Intent.addCategory(Intent.CATEGORY_HOME);
}
返回意图;
}这里mTopAction是String mTopAction=Intent.ACTION_MAIN,ACTION_MAIN是android.intent.action.MAIN。这里我们知道这是launcher的一个重要标志。我们在开发launcher的时候也是用这个来使用APP作为launcher。后续代码向意图添加一些参数。
代码注释2://在ActivityManagerService中
私人ActivityInforesolveActivityInfo(Intent意图,int标志,int userId){
活动信息ai=null;
ComponentName comp=Intent.getComponent();
尝试{
if (comp !=null) {
//工厂测试。
ai=AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); //从PackageManagerService中找到这个Activity
} 别的{
ResolveInfo信息=AppGlobals.getPackageManager().resolveIntent(
意图,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
标志、用户ID);
如果(信息!=null){
ai=信息.activityInfo;
}
}
} catch (RemoteException e) {
//忽略
}
返回艾伊;
}上诉代码只有一个目的,即根据意图从PackageManagerService 中找到此Activity。
注3:
mActivityStarter.startHomeActivityLocked是启动该Activity的方法。这个函数之后,操作就和正常的Activity启动一样了。我们这里就不详细介绍了。后面我们会详细介绍ActivityManagerService是如何运行的。此时,systemService 已经使用ActivityManagerService 启动了系统上的第一个应用程序启动器。
2.Launcher的图标显示。
我们知道,我们手机上的启动器启动后,我们手机上安装的所有应用程序都会以列表的形式显示出来。这是如何运作的?从上一篇文章的分析我们知道,这肯定和包管理服务PackageManagerService有关。现在我们来看看启动器主Activity启动后如何查找并使用所有APP。
主Activity 由启动器启动。
///packages/apps/launcher3/AndroidManifest.xml 从上面的xml文件中可以看到,"android.intent.action.MAIN注释的Activity是com.android.launcher3.Launcher,所以它是第一个Activity发射器。
1.1 Launcher的onCreate方法
@覆盖
protected void onCreate(Bundle savingInstanceState) {
……
LauncherAppState 应用程序=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 /* 通知监听器*/);
mExtractedColors=new ExtractedColors();
loadExtractedColorsAndColorItems();
mPopupDataProvider=new PopupDataProvider(this);
((AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE))
.addAccessibilityStateChangeListener(this);
锁定所有应用程序();
恢复状态(savedInstanceState);
如果(LauncherAppState.PROFILE_STARTUP){
Trace.endSection();
}
//仅当用户旋转(或触发
//配置更改)当启动器位于前台时
int currentScreen=PagedView.INVALID_RESTORE_PAGE;
if (savedInstanceState !=null) {
currentScreen=saveInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN, currentScreen);
}
if (!mModel.startLoader(currentScreen)) { //4 开始加载APP信息
//如果我们没有同步绑定,则在动画中显示淡入淡出
//第一页绑定完成。
mDragLayer.setAlpha(0);
} 别的{
//页面同步绑定。
mWorkspace.setCurrentPage(currentScreen);
设置工作空间加载(true);
}
.
}注1:获取LauncherAppState对象,并将Launcher对象设置为launcherAppState.LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(启动器);
返回mModel;
}
公共无效初始化(回调回调){
同步(mLock){
Preconditions.assertUIThread();
//删除所有排队的UI 可运行对象
mHandler.cancelAll();
mCallbacks=new WeakReference(回调);
}
}这里setLauncher是把launcher类对象作为弱引用放入mCallbacks中,WeakReference就是弱引用。
注3:该Activity的布局文件已加载。注意注释4中的:是非常重要的部分。这里我们开始加载手机中所有APP的数据//packages/apps/Launcher3/src/com/android/launcher3/LauncherModel
公共布尔startLoader(int synchronousBindPage){
同步(mLock){
.
if (mCallbacks !=null mCallbacks.get() !=null) {
最终回调oldCallbacks=mCallbacks.get();
//从同步加载进程中清除所有挂起的绑定运行对象。
runOnMainThread(new Runnable() {
公共无效运行(){
oldCallbacks.clearPendingBinds(); //1清除原来的内容
}
});
//如果已经有一个正在运行,则告诉它停止。
stopLoaderLocked();
mLoaderTask=new LoaderTask(mApp.getContext(), synchronousBindPage); //构建LoaderTask
if (synchronousBindPage !=PagedView.INVALID_RESTORE_PAGE
mModelLoaded !mIsLoaderTaskRunning) {
mLoaderTask.runBindSynchronousPage(synchronousBindPage);
返回真;
} 别的{
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
sWorker.post(mLoaderTask); //2 执行LoaderTask,sWorker是一个handler。
}
}
}
返回假;
注1执行原始回调,即清除启动器数据。注2进行LoaderTask的构建,sWorker执行loaderTask。 packages/apps/Launcher3/src/com/android/launcher3/LauncherModel--LoaderTask运行函数
公共无效运行(){
同步(mLock){
如果(mStopped){
返回;
}
mIsLoaderTaskRunning=true;
}
尝试{
if (DEBUG_LOADERS) Log.d(TAG, "步骤1.1: 加载工作区");
//在bindWorkspace()中设置为false
mIsLoadingAndBindingWorkspace=true;
加载工作空间();
验证未停止();
if (DEBUG_LOADERS) Log.d(TAG, "步骤1.2: 绑定工作空间工作空间");
绑定工作空间(mPageToBindFirst);
//休息一下
if (DEBUG_LOADERS) Log.d(TAG, "步骤1完成,等待空闲");
waitForIdle();
验证未停止();
//第二步
if (DEBUG_LOADERS) Log.d(TAG, "步骤2.1: 加载所有应用程序");
加载所有应用程序();
……
}
上述函数的每一步都有日志。翻译后很容易理解它的作用。
加载和绑定工作区:启动器使用工作区来显示系统上安装的应用程序图标。每个工作空间用来描述一个抽象桌面,它由N个桌面组成,每个桌面又分为N个单元格。 loadAllApps 加载所有应用程序private void loadAllApps() {
.
mBgAllAppsList.clear();
for (UserHandle 用户: 配置文件) {
//查询应用程序集
最终长qiaTime=DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
最终Listapps=mLauncherApps.getActivityList(null, user); //1 获取所有APP的launcher-Activity信息
.
mHandler.post(new Runnable() {
公共无效运行(){
最终长bindTime=SystemClock.uptimeMillis();
最终回调回调=tryGetCallbacks(oldCallbacks);
if (回调!=null) {
回调.bindAllApplications(添加); //2 绑定APP启动器信息。
} 别的{
Log.i(TAG, "不绑定apps: 没有启动器活动");
}
……
注1:获取所有APP的launcher Activity信息,因为每个APP只要有界面就一定有launcher Activity。注2:绑定所有APP信息。从前面的分析我们知道,回调就是Launcher类。我们来看看绑定了什么。公共无效bindAllApplications(最终ArrayListapps){
.
if (mAppsView !=null) {
mAppsView.setApps(应用程序); //1 将APP数据添加到mAppsVIew中,
}
如果(mLauncherCallbacks!=null){
mLauncherCallbacks.bindAllApplications(应用程序);
}
}重要代码,mAppsView是AllAppsContainerView,位置是/packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsContainerView,
AllAppsContainerView中的mApp是AlphabeticalAppsList,设置保存到其中。此时APP数据已加载完毕。
1.2 APP数据的展示。
上一节我们从Launcher类的oncreate函数了解到,它解析布局文件,最终调用setContentVIew为Activity设置界面。
mLauncherView=getLayoutInflater().inflate(R.layout.launcher, null);
setContentView(mLauncherView);这个加载布局包含上面提到的AllAppsContainerView,查看AllAppContainerVIew中的一个函数。
@覆盖
受保护无效onFinishInflate() {
super.onFinishInflate();
.
//加载所有应用程序回收器视图
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());
如果(FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP){
getRevealView().setVisibility(View.VISIBLE);
getContentView().setVisibility(View.VISIBLE);
getContentView().setBackground(null);
}
}该函数会在控件所在的xml加载完成后触发。这里的代码我们很熟悉。这是一个recyeleView的data、adapter和layoutManager的设置。这里的mAppRecyclerView重写了RecyclerView进行显示。所有已安装应用程序的图标等信息。
END,本文到此结束,如果可以帮助到大家,还望关注本站哦!
【深入解析启动应用程序进程的详细步骤】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
这篇文章讲的应该是电脑启动时会运行的那个程序吧?
有8位网友表示赞同!
我总觉得这个"launcher"词不太好理解,有没有图示解释一下?
有20位网友表示赞同!
我想知道不同的操作系统,launcher进程是怎么启动的呢?
有7位网友表示赞同!
应该会涉及到很多系统的核心文件和代码,挺复杂的啊!
有6位网友表示赞同!
这篇文章会不会有详细的步骤和操作说明?
有12位网友表示赞同!
我很想知道这个launcher进程到底干些什么?
有9位网友表示赞同!
有没有人做过对launcher进程启动过程的分析吗?
有12位网友表示赞同!
我最近觉得电脑启动有点慢,是不是launcher进程有问题啊?
有16位网友表示赞同!
启动launcher进程耗费多少CPU资源呢?
有18位网友表示赞同!
这篇文章的内容应用场景很多吧,比如程序开发啊什么的
有5位网友表示赞同!
这个"启动"的过程是物理性的还是虚拟的?
有10位网友表示赞同!
估计这篇文章会提到一些系统级的工具和命令吧?
有13位网友表示赞同!
我有点好奇launcher进程在启动的时候会加载哪些驱动或者模块?
有15位网友表示赞同!
学习完这篇文章,我是不是可以自己修改launcher进程呢?
有6位网友表示赞同!
感觉这篇文章难度不低啊,需要有一定的系统知识和编程基础吧!
有19位网友表示赞同!
有没有人做过关于launcher进程安全的评测吗?
有12位网友表示赞同!
启动launcher进程会对系统内存有很大的占用吗?
有14位网友表示赞同!
是不是不同的软件都会有一个自己的launcher进程?
有15位网友表示赞同!
我觉得这篇文章内容很有用,可以帮助我更好地理解电脑运行机制!
有16位网友表示赞同!