这篇主要讲解的是Launcher程序的启动流程至于Launcher前面的系统进程启动流程大家可以看看我的Android应用跟系统之间通信什么时候用Socket什么时候用Binder结合源码详解有介绍。好了进入咱们今天的主题Launcher,注意本篇系统源码是基于Android4.4版本(也就是下面AMS、PMS的源码),先看看Launcher启动入口在哪里其实就在SystemServer中:
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
......
// Start services.
try {
......
startOtherServices();
......
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
......
}
没错就是它startOtherServices,来看一下源码run方法的startOtherServices:
private void startOtherServices() {
......
mActivityManagerService.systemReady(() -> {
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();
......
}
}
我们再来看一看ActivityManagerService源码的systemReady方法吧:
public void systemReady(final Runnable goingCallback) {
......
synchronized(this) {
// Make sure we have no pre-ready processes sitting around.
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
ResolveInfo ri = mContext.getPackageManager()
.resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
STOCK_PM_FLAGS);
CharSequence errorMsg = null;
if (ri != null) {
ActivityInfo ai = ri.activityInfo;
ApplicationInfo app = ai.applicationInfo;
if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
mTopAction = Intent.ACTION_FACTORY_TEST;
mTopData = null;
mTopComponent = new ComponentName(app.packageName,
ai.name);
} else {
errorMsg = mContext.getResources().getText(
com.android.internal.R.string.factorytest_not_system);
}
} else {
errorMsg = mContext.getResources().getText(
com.android.internal.R.string.factorytest_no_action);
}
if (errorMsg != null) {
mTopAction = null;
mTopData = null;
mTopComponent = null;
Message msg = Message.obtain();
msg.what = SHOW_FACTORY_ERROR_MSG;
msg.getData().putCharSequence("msg", errorMsg);
mHandler.sendMessage(msg);
}
}
}
synchronized (this) {
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android")) {
addAppLocked(info, false);
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
// Start up initial activity.
mBooting = true;
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Message msg = Message.obtain();
msg.what = SHOW_UID_ERROR_MSG;
mHandler.sendMessage(msg);
}
} catch (RemoteException e) {
}
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
}
}, 0, null, null,
android.Manifest.permission.INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
mStackSupervisor.resumeTopActivitiesLocked();
sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
}
}
找到mStackSupervisor.resumeTopActivitiesLocked():
boolean resumeTopActivitiesLocked() {
return resumeTopActivitiesLocked(null, null, null);
}
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
boolean result = false;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (isFrontStack(stack)) {
if (stack == targetStack) {
result = stack.resumeTopActivityLocked(target, targetOptions);
} else {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}
接下来我们再看看ActivityStack的resumeTopActivityLocked方法:
final boolean resumeTopActivityLocked(ActivityRecord prev) {
return resumeTopActivityLocked(prev, null);
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
......
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return mStackSupervisor.resumeHomeActivity(prev);
}
}
看到返回的是ActivityStackSupervisor的resumeHomeActivity方法:
boolean resumeHomeActivity(ActivityRecord prev) {
moveHomeToTop();
if (prev != null) {
prev.task.mOnTopOfHome = false;
}
ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
if (r != null && r.isHomeActivity()) {
mService.setFocusedActivityLocked(r);
return resumeTopActivitiesLocked(mHomeStack, prev, null);
}
return mService.startHomeActivityLocked(mCurrentUser);
}
这里返回的是ActivityManagerService的startHomeActivityLocked方法:
boolean startHomeActivityLocked(int userId) {
if (mHeadless) {
// Added because none of the other calls to ensureBootCompleted seem to fire
// when running headless.
ensureBootCompleted();
return false;
}
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
&& mTopAction == 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();
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.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mStackSupervisor.startHomeActivity(intent, aInfo);
}
}
return true;
}
终于来到了要点了getHomeIntent:
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
这里启动的程序就是Launcher,如果对Launcher程序感兴趣我可以贴上Launcher的AndroidManifest.xml源码:
<?xml version="1.0" encoding="utf-8"?>
<!--
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
<permission
android:name="com.android.launcher3.permission.PRELOAD_WORKSPACE"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="system|signature" />
<permission
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="dangerous"
android:label="@string/permlab_install_shortcut"
android:description="@string/permdesc_install_shortcut" />
<permission
android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="dangerous"
android:label="@string/permlab_uninstall_shortcut"
android:description="@string/permdesc_uninstall_shortcut"/>
<permission
android:name="com.android.launcher3.permission.READ_SETTINGS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
android:label="@string/permlab_read_settings"
android:description="@string/permdesc_read_settings"/>
<permission
android:name="com.android.launcher3.permission.WRITE_SETTINGS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
android:label="@string/permlab_write_settings"
android:description="@string/permdesc_write_settings"/>
<permission
android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS"
android:protectionLevel="signature"
/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" />
<application
android:name="com.android.launcher3.LauncherApplication"
android:label="@string/application_name"
android:icon="@mipmap/ic_launcher_home"
android:hardwareAccelerated="true"
android:largeHeap="@bool/config_largeHeap"
android:supportsRtl="true">
<activity
android:name="com.android.launcher3.Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:theme="@style/Theme"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="nosensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
</activity>
<activity
android:name="com.android.launcher3.ToggleWeightWatcher"
android:label="@string/toggle_weight_watcher"
android:enabled="@bool/debug_memory_enabled"
android:icon="@mipmap/ic_launcher_home">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.android.launcher3.WallpaperPickerActivity"
android:theme="@style/Theme.WallpaperCropper"
android:label="@string/pick_wallpaper"
android:icon="@mipmap/ic_launcher_wallpaper"
android:finishOnCloseSystemDialogs="true"
android:process=":wallpaper_chooser">
<intent-filter>
<action android:name="android.intent.action.SET_WALLPAPER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.android.launcher3.WallpaperCropActivity"
android:theme="@style/Theme.WallpaperCropper"
android:label="@string/crop_wallpaper"
android:icon="@mipmap/ic_launcher_wallpaper"
android:finishOnCloseSystemDialogs="true"
android:process=":wallpaper_chooser">
<intent-filter>
<action android:name="android.service.wallpaper.CROP_AND_SET_WALLPAPER" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
<!-- Debugging tools -->
<activity
android:name="com.android.launcher3.MemoryDumpActivity"
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/debug_memory_activity"
android:enabled="@bool/debug_memory_enabled"
android:excludeFromRecents="true"
android:icon="@mipmap/ic_launcher_home"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.android.launcher3.MemoryTracker"
android:enabled="@bool/debug_memory_enabled"
>
</service>
<!-- Intent received used to prepopulate the default workspace. -->
<receiver
android:name="com.android.launcher3.PreloadReceiver"
android:permission="com.android.launcher3.permission.PRELOAD_WORKSPACE">
<intent-filter>
<action android:name="com.android.launcher3.action.PRELOAD_WORKSPACE" />
</intent-filter>
</receiver>
<!-- Intent received used to install shortcuts from other applications -->
<receiver
android:name="com.android.launcher3.InstallShortcutReceiver"
android:permission="com.android.launcher3.permission.INSTALL_SHORTCUT">
<intent-filter>
<action android:name="com.android.launcher3.action.INSTALL_SHORTCUT" />
</intent-filter>
</receiver>
<!-- Intent received used to uninstall shortcuts from other applications -->
<receiver
android:name="com.android.launcher3.UninstallShortcutReceiver"
android:permission="com.android.launcher3.permission.UNINSTALL_SHORTCUT">
<intent-filter>
<action android:name="com.android.launcher3.action.UNINSTALL_SHORTCUT" />
</intent-filter>
</receiver>
<!-- New user initialization; set up initial wallpaper -->
<receiver
android:name="com.android.launcher3.UserInitializeReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.USER_INITIALIZE" />
</intent-filter>
</receiver>
<receiver android:name="com.android.launcher3.PackageChangedReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_CHANGED"/>
<action android:name="android.intent.action.PACKAGE_REPLACeD"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"></data>
</intent-filter>
</receiver>
<!-- The settings provider contains Home's data, like the workspace favorites -->
<provider
android:name="com.android.launcher3.LauncherProvider"
android:authorities="com.android.launcher3.settings"
android:exported="true"
android:writePermission="com.android.launcher3.permission.WRITE_SETTINGS"
android:readPermission="com.android.launcher3.permission.READ_SETTINGS" />
<meta-data android:name="android.nfc.disable_beam_default"
android:value="true" />
</application>
</manifest>
再看看frameworks\base\services\java\com\android\server\pm\PackageManagerService.java:
if (pkg.packageName.equals("android")) {
synchronized (mPackages) {
if (mAndroidApplication != null) {
Slog.w(TAG, "*************************************************");
Slog.w(TAG, "Core android package being redefined. Skipping.");
Slog.w(TAG, " file=" + mScanningPath);
Slog.w(TAG, "*************************************************");
mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
return null;
}
// Set up information for our fall-back user intent resolution activity.
mPlatformPackage = pkg;
pkg.mVersionCode = mSdkVersion;
mAndroidApplication = pkg.applicationInfo;
if (!mResolverReplaced) {
mResolveActivity.applicationInfo = mAndroidApplication;
mResolveActivity.name = ResolverActivity.class.getName();
mResolveActivity.packageName = mAndroidApplication.packageName;
mResolveActivity.processName = "system:ui";
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
mResolveActivity.exported = true;
mResolveActivity.enabled = true;
mResolveInfo.activityInfo = mResolveActivity;
mResolveInfo.priority = 0;
mResolveInfo.preferredOrder = 0;
mResolveInfo.match = 0;
mResolveComponentName = new ComponentName(
mAndroidApplication.packageName, mResolveActivity.name);
}
}
}
这里是存储Launcher信息的,大家可以看到Launcher在system_server进程中开了个子进程"system:ui"进程,感兴趣的可以下载Android系统源码看完整源码详解,这里就先讲到这。