Android的Launcher启动过程分析(1)
通过上篇文章我们了解了AndroidLauncher的启动过程,下面我们继续探究点击Launcher中图片启动应用的过程。
通过上篇文章我们知道,最终ActivityStartController的startHomeActivity(Intent intent, ActivityInfo aInfo, String reason)函数启动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();
}
}
最终会调用ActivityStarter.startActivity函数将各种启动参数输入。
下面我们来看Launcher的onCreat方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
LauncherAppState app = LauncherAppState.getInstance();//tag1
mDeviceProfile = getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE ?
app.getInvariantDeviceProfile().landscapeProfile
: app.getInvariantDeviceProfile().portraitProfile;
mSharedPrefs = Utilities.getPrefs(this);
mIsSafeModeEnabled = getPackageManager().isSafeMode();
mModel = app.setLauncher(this);//tag2
....
if (!mRestoring) {
if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);//2
} else {
mModel.startLoader(mWorkspace.getRestorePage());
}
}
...
}
tag1处获取LauncherAppState的实例并在注释tag2处调用它的setLauncher函数并将Launcher对象传入,LauncherAppState的setLauncher函数如下所示:
LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
return mModel;
}
我们看到mModel.initialize(launcher)函数,代码如下:
/**
* Set this as the current Launcher activity object for the loader.
*/
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
Preconditions.assertUIThread();
mCallbacks = new WeakReference<>(callbacks);
}
}
在initialize函数中会将Callbacks,也就是传入的Launcher 封装成一个弱引用对象。因此我们得知mCallbacks变量指的就是封装成弱引用对象的Launcher,这个mCallbacks后文会用到它。
再回到Launcher的onCreate函数,在tag2处调用了LauncherModel的startLoader函数:
@Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");//tag1
static {
sWorkerThread.start();
}
@Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());//tag2
...
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();
LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
mBgAllAppsList, synchronousBindPage, mCallbacks);//tag3
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;
}
tag1处创建了具有消息循环的线程HandlerThread对象。tag2处创建了Handler,并且传入HandlerThread的Looper。Hander的作用就是向HandlerThread发送消息的,如果已经load或者正在load就直接绑定数据,否者接着看startLoaderForResults函数如下:
public void startLoaderForResults(LoaderResults results) {
synchronized (mLock) {
stopLoader();
mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
runOnWorkerThread(mLoaderTask);
}
}
我们看到先将load任务停止,然后创建一个LoaderTask(Runnable)对像,同时调用 runOnWorkerThread(mLoaderTask);函数如下:
/** Runs the specified runnable immediately if called from the worker thread, otherwise it is
* posted on the worker thread handler. */
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 handler
sWorker.post(r);
}
}
如果没有工作在worker thread线程的话直接调用handler通讯将Runnable发送给HandlerThread,否者直接调用Runnable的run函数,LoaderTask的run方法如下:
public void run() {
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
TraceHelper.partitionSection(TAG, "step 1.1: loading workspace");
loadWorkspace();
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace");
mResults.bindWorkspace();
// Notify the installer packages of packages with active installs on the first screen.
TraceHelper.partitionSection(TAG, "step 1.3: send first screen broadcast");
sendFirstScreenActiveInstallsBroadcast();
// Take a break
TraceHelper.partitionSection(TAG, "step 1 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// second step
TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
loadAllApps();
TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
verifyNotStopped();
mResults.bindAllApps();
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache");
updateIconCache();
// Take a break
TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// third step
TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts");
loadDeepShortcuts();
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts");
mResults.bindDeepShortcuts();
// Take a break
TraceHelper.partitionSection(TAG, "step 3 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// fourth step
TraceHelper.partitionSection(TAG, "step 4.1: loading widgets");
mBgDataModel.widgetsModel.update(mApp, null);
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 4.2: Binding widgets");
mResults.bindWidgets();
transaction.commit();
} catch (CancellationException e) {
// Loader stopped, ignore
TraceHelper.partitionSection(TAG, "Cancelled");
}
TraceHelper.endSection(TAG);
}
auncher是用工作区的形式来显示系统安装的应用程序的快捷图标,每一个工作区都是来描述一个抽象桌面的,它由n个屏幕组成,每个屏幕又分n个单元格,每个单元格用来显示一个应用程序的快捷图标。step 1.1处调用loadWorkspace()函数用来加载工作区信息,step 1.2调用 mResults.bindWorkspace()来绑定工作区信息;step2.1处的loadAllApps()函数是用来加载系统已经安装的应用程序信息,step2.2处调用mResults.bindAllApps()绑定已安装应用程序信息,这里我们来看下loadAllApps函数代码如下所示:
private void loadAllApps() {
final List<UserHandle> profiles = mUserManager.getUserProfiles();
// Clear the list of apps
mBgAllAppsList.clear();
for (UserHandle user : profiles) {
// Query for the set of apps
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
// Fail if we don't have any apps
// TODO: Fix this. Only fail for the current user.
if (apps == null || apps.isEmpty()) {
return;
}
boolean quietMode = mUserManager.isQuietModeEnabled(user);
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfo app = apps.get(i);
// This builds the icon bitmaps.
mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
}
}
if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
// get all active sessions and add them to the all apps list
for (PackageInstaller.SessionInfo info :
mPackageInstaller.getAllVerifiedSessions()) {
mBgAllAppsList.addPromiseApp(mApp.getContext(),
PackageInstallerCompat.PackageInstallInfo.fromInstallingState(info));
}
}
mBgAllAppsList.added = new ArrayList<>();
通过LauncherAppsCompat.getActivityList(null, user)函数获取app,并且封装成AppInfo存储在mBgAllAppsList中,这里的getActivityList函数是调用的LauncherAppsCompatVL中的,代码如下:
public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
ParceledListSlice<ResolveInfo> activities = null;
try {
activities = mService.getLauncherActivities(packageName, user);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
if (activities == null) {
return Collections.EMPTY_LIST;
}
ArrayList<LauncherActivityInfo> lais = new ArrayList<LauncherActivityInfo>();
for (ResolveInfo ri : activities.getList()) {
LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
if (DEBUG) {
Log.v(TAG, "Returning activity for profile " + user + " : "
+ lai.getComponentName());
}
lais.add(lai);
}
return lais;
}
我们看到mService.getLauncherActivities(packageName, user),这里的mService是 ILauncherApps.aidl,通过IPC获取ILauncherApps的。回到LoaderTask的run方法中,我们看到继续执行step2.2 mResults.bindAllApps(),代码如下:
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();
if (callbacks != null) {
callbacks.bindAllApplications(list);
}
}
};
mUiExecutor.execute(r);
}
这里的callBacks就是Launcher实例,所以我们直接去看Launcher的bindAllApplications方法代码如下:
public void bindAllApplications(ArrayList<AppInfo> apps) {
mAppsView.getAppsStore().setApps(apps);//tag1
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAllApplications(apps);
}
}
在tag1处会调用AllAppsContainerView的setApps函数,并将包含应用信息的列表apps传进去,AllAppsContainerView的setApps函数如下所示:
包含应用信息的列表apps已经传给了AllAppsContainerView,查看AllAppsContainerView的setApps函数:
void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
appsList.updateItemFilter(matcher);
recyclerView = (AllAppsRecyclerView) rv;
recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
recyclerView.setApps(appsList, mUsingTabs);//tag1
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);//tag2
recyclerView.setHasFixedSize(true);
// No animations will occur when changes occur to the items in this RecyclerView.
recyclerView.setItemAnimator(null);
FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
recyclerView.addItemDecoration(focusedItemDecorator);
adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
applyVerticalFadingEdgeEnabled(verticalFadingEdge);
applyPadding();
}
tag1处得到AllAppsRecyclerView用来显示App列表,并将apps的信息列表传进去,并在tag2处为AllAppsRecyclerView设置Adapter。这样应用程序快捷图标的列表就会显示在屏幕上。
Launcher启动流程就讲到这里,不足之处还请指正。
总结一下Android系统的启动流程大体如下:
1.启动电源以及系统启动
当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。
2.引导程序BootLoader
引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
3.Linux内核启动
内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。
4.init进程启动
初始化和启动属性服务,并且启动Zygote进程。
5.Zygote进程启动
创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动SystemServer进程。
6.SystemServer进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
7.Launcher启动
被SystemServer进程启动的ActivityManagerService会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。