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();
.....
}
}
上面函数每一步都有日志,翻译过来很好理解它做了什么,
- 加载和绑定工作区:Launcher是用工作区来显示系统安装的应用图标的,每个工作区都用来描述一个抽象桌面,它由N个桌面构成,每个桌面又分N个单元格。
- 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系统启动的过程文章,欢迎投稿。