《App的安装过程》一篇我们分析了系统启动后,程序是如何被安装到系统中的。安装完成后,我们会看到桌面将显示一个图标,用于点击启动App,这篇继续分析图标的显示过程。
系统提供了一个Home程序,即Launcher,用来显示系统中已经安装的程序,它是有SystemServer进程启动的,它也是第一个启动的应用程序。
Launcher根据android.intent.action.MAIN和android.intent.category.LAUNCHER两个条件,将应用入口封装成一个快捷图标,就能启动跳转到对应的程序。因此我们分析Launcher启动就能知道桌面图标的显示过程,我们从SystemServer开始看。
SystemServer的run方法会启动许多服务,包含三类BootstrapServices、CoreServices和OtherServices,Launcher的启动在OtherServices中。
//运行
private void run() {
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
mProfilerSnapshotTimer = new Timer();
mProfilerSnapshotTimer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
VMRuntime.getRuntime().clearGrowthLimit();
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Build.ensureFingerprintProperty();
Environment.setUserRequired(true);
BinderInternal.disableBackgroundScheduling(true);
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
//加载services/core/jni/中的cpp代码,初始化各种“本地服务”,看目录下onload.cpp,将java本地方法映射为c函数,java->c,
System.loadLibrary("android_servers");
//调用services/core/jni/com_android_server_SystemServer.cpp
nativeInit();
performPendingShutdown();
createSystemContext();
//创建SystemServiceManager,用来管理各种系统service
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
try {
//启动PMS,AMS等服务
startBootstrapServices();
// 启动LED、电池等核心服务
startCoreServices();
//启动IputManagerService等服务
startOtherServices();
} catch (Throwable ex) {
throw ex;
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
PMS,AMS等服务会优先启动,其次是电池和LED等核心服务,最后才是其他服务,如WMS、IMS等,Launcher也是在这个方法启动的。
......
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
......
当系统完成各种服务的注册和启动后,将调用AMS的systemReady方法作为入口,让AMS启动Launcher界面。
public void systemReady(final Runnable goingCallback) {
synchronized(this) {
......
mBooting = true;
//启动Launcher
startHomeActivityLocked(mCurrentUserId);
......
}
}
boolean startHomeActivityLocked(int userId) {
//mFactoryTest描述系统的运行模式,分工厂非工厂,工厂分低级和高级
//mTopAction非工厂和高级工厂,mTopAction为Intent.ACTION_MAIN
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
return false;
}
//构建跳转Intent
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
//获取app的进程
ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid, true);
//加载首个Home程序Launcher时app为null
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
//到mStackSupervisor维护了所有的任务栈
mStackSupervisor.startHomeActivity(intent, aInfo);
}
}
return true;
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
//添加CATEGORY_HOME
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
系统运行模式分两类:工厂测试和非工厂测试。工厂测试分为:低级工厂测试和高级工厂测试。在非工厂测试和高级模式中,mTopAction为Intent .ACTION_MAIN,mTopData 和都为null。假设我们当前运行在非工厂测试模式下,可以看到Category添加了一个Intent.CATEGORY_HOME,它配合Intent .ACTION_MAIN就构成了我们要跳转的Home程序的MainActivity。我们看一眼AndroidManifest.xml文件。
<application
android:name="com.android.launcher2.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.launcher2.Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:resumeWhilePausing="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>
系统用一个ProcessRecord类来描述一个应用程序的进程,由于系统还没有启动过任何程序,getProcessRecordLocked首次将返回null。mStackSupervisor是ActivityStackSupervisor类型,对任务栈管理器ActivityStack的管理,ActivityStack则是对任务栈TaskRecord的管理,而每个Activity在任务栈中都使用ActivityRecord来进行描述。我们通常所说的Activity入栈,指的就是将ActivityRecord添加到对应的TaskRecord中。
void startHomeActivity(Intent intent, ActivityInfo aInfo) {
moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
//验证Intent
startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null,
0, 0, 0, null, false, null, null, null);
}
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
//ProcessRecord用来描述一个应用程序的进程,并保存在AMS内部
ProcessRecord callerApp = null;
if (caller != null) {
//caller指向ApplicationThread,即让ProcessRecord指向所运行的应用程序
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//获取进程pid
callingPid = callerApp.pid;
//获取进程uid
callingUid = callerApp.info.uid;
} else {
err = ActivityManager.START_PERMISSION_DENIED;
}
}
......
//创建ActivityRecord,用来描述启动入口的MainActivity
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, this, container, options);
if (outActivity != null) {
outActivity[0] = r;
}
final ActivityStack stack = getFocusedStack();
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
if (mService.mDidAppSwitch) {
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
doPendingActivityLaunchesLocked(false);
//验证完成,开始启动模式判断
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
if (err < 0) {
notifyActivityDrawnForKeyguard();
}
return err;
}
根据callingPid和callingUid 构建了一个ActivityRecord,前面说过,它用来描述Launcher程序的ManActivity在栈中的信息。注意倒数第三个参数doResume为true。
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
ActivityStack targetStack;
intent.setFlags(launchFlags);
if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| launchSingleInstance || launchSingleTask) {
if (inTask == null && r.resultTo == null) {
ActivityRecord intentActivity = !launchSingleInstance ?
findTaskLocked(r) : findActivityLocked(intent, r.info);
if (intentActivity != null) {
if (isLockTaskModeViolation(intentActivity.task)) {
showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (r.task == null) {
r.task = intentActivity.task;
}
//获取栈管理器
targetStack = intentActivity.task.stack;
targetStack.mLastPausedActivity = null;
......
targetStack.mLastPausedActivity = null;
//获取Activity栈开启
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
if (!launchTaskBehind) {
mService.setFocusedActivityLocked(r);
}
return ActivityManager.START_SUCCESS;
}
targetStack为ActivityStack类型 ,它管理了多个任务栈TaskRecord 。
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
......
//执行resume
if (doResume) {
//resume顶部的Activity
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}
又回到了大管家ActivityStackSupervisor的resumeTopActivitiesLocked方法。
boolean resumeTopActivitiesLocked() {
return resumeTopActivitiesLocked(null, null, null);
}
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
boolean result = false;
if (isFrontStack(targetStack)) {
//再次调用了targetStack的resumeTopActivityLocked,此时mResumedActivity==null了
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack == targetStack) {
continue;
}
if (isFrontStack(stack)) {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}
这里从新回到TargetStack,是因为必须判断当前栈顶是否有未pause的Activity,如果有的话先暂停旧的Activity,才会resume新的Activity。
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
if (!mService.mBooting && !mService.mBooted) {!
return false;
}
ActivityRecord parent = mActivityContainer.mParentActivity;
if ((parent != null && parent.state != ActivityState.RESUMED) ||
!mActivityContainer.isAttachedLocked()) {
return false;
}
cancelInitializingActivities();
//获取栈顶不是处于结束状态的Activity,next即指向了MainAcivity
ActivityRecord next = topRunningActivityLocked(null);
.....
//先执行当前Activity的Pause,再执行新的resume
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
//执行pause,即Launcher进入Pause,然后再启动next,即MainActivity
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
......
//开启新的Activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
next表示我们正准备启动的Activity,mResumedActivity 表示将被关闭的Activity,如果mResumedActivity 不为null,表示还没有执行pause,将先调用startPausingLocked来执行。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//每个Activity都会记录当前的进程名和用户id,如果这个进程存在,就通知AMS将这个Activity启动起来
//不存在则根据进程名和用户id,创建新的进程,再启动activity
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
//进程存在,直接启动
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//启动新activity
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
//第一次点击图标,进程不在,新建
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
根据进程名和用户id从AMS中获取当前的进程,获取成功返回一个ProcessRecord对象,它是对应用程序进程的描述,如果存在,则调用realStartActivityLocked开启新的Activity;如果不存在,将执行startProcessLocked方法通知Zygote启动新进程。我们先看AMS如何通知的。
//生成新进程
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
//先新建ProcessRecord,保存进程信息
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkTime(startTime, "startProcess: after getProcessRecord");
} else {
app = null;
}
if (app != null && app.pid > 0) {
if (!knownToBeDead || app.thread == null) {
app.addPackage(info.packageName, info.versionCode, mProcessStats);
return app;
}
Process.killProcessGroup(app.info.uid, app.pid);
handleAppDiedLocked(app, true, true);
checkTime(startTime, "startProcess: done killing old proc");
}
String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;
if (!isolated) {
if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
if (mBadProcesses.get(info.processName, info.uid) != null) {
return null;
}
} else {
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mBadProcesses.remove(info.processName, info.uid);
if (app != null) {
app.bad = false;
}
}
}
}
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
app.crashHandler = crashHandler;
if (app == null) {
return null;
}
mProcessNames.put(processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
} else {
//添加包名、版本号和进程状态
app.addPackage(info.packageName, info.versionCode, mProcessStats);
}
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
return app;
}
//通知Zygote创建一个新的进程
startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
return (app.pid != 0) ? app : null;
}
ProcessRecord 保存了包名,版本号等信息,传递给startProcessLocked的另一个重载方法。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
......
//告诉Zygote子进程孵化ActivityThread进程后,调用main方法
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//开启进程
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
Process是用来管理系统应用程序进程的工具,静态方法start,将使用Socket通讯连接上Zygote,让其孵化新的进程ActivityThread,并运行ActivityThread的main方法。
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
//使用ArrayList保存uid等数据
ArrayList<String> argsForZygote = new ArrayList<String>();
argsForZygote.add("--runtime-init");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
argsForZygote.add("--enable-debugger");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
argsForZygote.add("--enable-checkjni");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
argsForZygote.add("--mount-external-multiuser");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
argsForZygote.add("--mount-external-multiuser-all");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");
int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}
if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}
if (instructionSet != null) {
argsForZygote.add("--instruction-set=" + instructionSet);
}
if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
//连接Zygote并发送请求取得结果
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
openZygoteSocketIfNeeded用于连接Zygote,并返回连接状态。zygoteSendArgsAndGetResult用于发送请求并取得响应数据。
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//连接Zygote
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
//尝试第二次连接
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
为了和Zygote进行Socket通讯,这里做了两次连接尝试,让后将连接状态返回。
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
//向Zygote发送请求数据
writer.write(Integer.toString(args.size()));
writer.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
//构建ProcessStartResult
ProcessStartResult result = new ProcessStartResult();
//从流数据读取pid
result.pid = inputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
如果进程创建成功,pid进程id将不小于0,否则说明创建失败了。关于Zygote是如何接受请求的,我们留到新的篇章分析。
我们回过头来分析realStartActivityLocked方法。
final boolean realStartActivityLocked(ActivityRecord r,ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
//冻结未启动的其他Activity
r.startFreezingScreenLocked(app, 0);
if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
//向WindowManager设置Token,标识当前App要位于前台显示
mWindowManager.setAppVisibility(r.appToken, true);
//搜索启动较慢的App的信息
r.startLaunchTickingLocked();
//检查配置信息
if (checkConfig) {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken : null);
mService.updateConfigurationLocked(config, r, false, false);
}
r.app = app;//记录了当前Activity在哪个进程上运行的
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
if (localLOGV) Slog.v(TAG, "Launching: " + r);
int idx = app.activities.indexOf(r);
if (idx < 0) {
app.activities.add(r);//将Activity将入到进程维护的activity列表中
}
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
final ActivityStack stack = r.task.stack;
try {
if (app.thread == null) {
throw new RemoteException();
}
List<ResultInfo> results = null;
List<Intent> newIntents = null;
//是否调用onResume,上面传入了ture
if (andResume) {
results = r.results;
newIntents = r.newIntents;
}
if (andResume) {
EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
r.userId, System.identityHashCode(r),
r.task.taskId, r.shortComponentName);
}
//是否桌面Activity,如果是,添加到Activity栈底部
if (r.isHomeActivity() && r.isNotResolverActivity()) {
// Home process is the root process of the task.
mService.mHomeProcess = r.task.mActivities.get(0).app;
}
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
r.sleeping = false;
r.forceNewConfig = false;
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
String profileFile = null;
ParcelFileDescriptor profileFd = null;
if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
if (mService.mProfileProc == null || mService.mProfileProc == app) {
mService.mProfileProc = app;
profileFile = mService.mProfileFile;
profileFd = mService.mProfileFd;
}
}
app.hasShownUi = true;
app.pendingUiClean = true;
if (profileFd != null) {
try {
profileFd = profileFd.dup();
} catch (IOException e) {
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException o) {
}
profileFd = null;
}
}
}
ProfilerInfo profilerInfo = profileFile != null
? new ProfilerInfo(profileFile, profileFd, mService.mSamplingInterval,
mService.mAutoStopProfiler) : null;
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
//app为ProcessRecord,封装了进程的信息
//app.thread为IApplicationThread,用于ApplicationThread和AMS之间的通信
//经过上面的赋值操作,回到ActivityThread的内部类ApplicationThread调用scheduleLaunchActivity,设置所有参数,再调用Handler发送消息调用handleLaunchActivity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
results, newIntents, !andResume, mService.isNextTransitionForward(),
profilerInfo);
.....
thread为IApplicationThread类型,当新的进程被创建,主线程ActivityThread被构建,它的成员变量ApplicationThread就被初始化,它继承自ApplicationThreadNative,本质是一个Binder,用于跨进程和AMS进行通讯。
final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
final SparseArray<ForegroundToken> mForegroundProcesses = new SparseArray<ForegroundToken>();
final ArrayList<ProcessRecord> mProcessesOnHold = new ArrayList<ProcessRecord>();
final ArrayList<ProcessRecord> mPersistentStartingProcesses = new ArrayList<ProcessRecord>();
final ArrayList<ProcessRecord> mRemovedProcesses = new ArrayList<ProcessRecord>();
final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
int mLruProcessActivityStart = 0;
int mLruProcessServiceStart = 0;
final ArrayList<ProcessRecord> mProcessesToGc = new ArrayList<ProcessRecord>();
final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
AMS使用了许多个列表,来保存不同状态下进程的ProcessRecord,ProcessRecord的成员变量thread则持有ApplicationThread的远程代理接口IApplicationThread ,因此AMS和ActivityThread能进行通讯。
final class ProcessRecord {
......
IApplicationThread thread;
scheduleLaunchActivity方法用于正式启动Activity并显示,我们将在《Activity的启动过程》和《Activity渲染过程》中详细分析。
我们知道启动Home的LaunerActivity成功后,最终会执行到onCreate方法。
public class Launcher extends BaseDraggingActivity implements LauncherExterns,
LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{
......
@Thunk AllAppsContainerView mAppsView; //所有App图标的容器
AllAppsTransitionController mAllAppsController;//对图标的控制器
......
//管理Launcher界面的中的数据,统合管理App,AppWidget等的读取
private LauncherModel mModel;
private ModelWriter mModelWriter;
private IconCache mIconCache;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
......
@Override
protected void onCreate(Bundle savedInstanceState) {
TraceHelper.beginSection("Launcher-onCreate");
super.onCreate(savedInstanceState);
TraceHelper.partitionSection("Launcher-onCreate", "super call");
LauncherAppState app = LauncherAppState.getInstance(this);
mOldConfig = new Configuration(getResources().getConfiguration());
//初始化整个界面的Model
mModel = app.setLauncher(this);
initDeviceProfile(app.getInvariantDeviceProfile());
mSharedPrefs = Utilities.getPrefs(this);
mIconCache = app.getIconCache();
mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);
mDragController = new DragController(this);
//初始化控制器
mAllAppsController = new AllAppsTransitionController(this);
mStateManager = new LauncherStateManager(this);
UiFactory.onCreate(this);
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
mAppWidgetHost = new LauncherAppWidgetHost(this);
mAppWidgetHost.startListening();
mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null);
//初始化图标容器
setupViews();
......
//加载安装的应用程序
if (!mModel.startLoader(currentScreen)) {
if (!internalStateHandled) {
mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
}
} else {
mWorkspace.setCurrentPage(currentScreen);
setWorkspaceLoading(true);
}
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
//显示桌面布局
setContentView(mLauncherView);
......
}
这里有几个很关键的方法,LauncherAppState用于保存Launcher程序的状态,它使用setLauncher方法初始化LauncherModel ,
public class LauncherAppState {
public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
private static LauncherAppState INSTANCE;
private final Context mContext;
private final LauncherModel mModel;
.....
private LauncherAppState(Context context) {
if (getLocalProvider(context) == null) {
throw new RuntimeException(
"Initializing LauncherAppState in the absence of LauncherProvider");
}
Log.v(Launcher.TAG, "LauncherAppState initiated");
Preconditions.assertUIThread();
mContext = context;
mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
//构造LauncherModel
mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
......
}
LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
//初始化LauncherModel
mModel.initialize(launcher);
return mModel;
}
看初始化LauncherModel的方法initialize。
public class LauncherModel extends BroadcastReceiver
implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
@Thunk WeakReference<Callbacks> mCallbacks;
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
Preconditions.assertUIThread();
//LauncherModel可调用Launcher实现的方法
mCallbacks = new WeakReference<>(callbacks);
}
}
public interface Callbacks {
public void rebindModel();
public int getCurrentWorkspaceScreen();
public void clearPendingBinds();
public void startBinding();
public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons);
public void bindScreens(ArrayList<Long> orderedScreenIds);
public void finishFirstPageBind(ViewOnDrawExecutor executor);
public void finishBindingItems();
public void bindAllApplications(ArrayList<AppInfo> apps);
public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps);
public void bindAppsAdded(ArrayList<Long> newScreens,
ArrayList<ItemInfo> addNotAnimated,
ArrayList<ItemInfo> addAnimated);
public void bindPromiseAppProgressUpdated(PromiseAppInfo app);
public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated, UserHandle user);
public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher);
public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos);
public void bindAllWidgets(ArrayList<WidgetListRowEntry> widgets);
public void onPageBoundSynchronously(int page);
public void executeOnNextDraw(ViewOnDrawExecutor executor);
public void bindDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMap);
}
LauncherModel的初始化是为了构建Callbacks接口,而这个接口被Launcher实现了。
public class Launcher extends BaseDraggingActivity implements LauncherExterns,
LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate{
AllAppsController服务于AllAppsContainerView,帮助处理所有App的拖拽等事件。我们会在setupViews方法里看到他们的关联。
private void setupViews() {
mDragLayer = findViewById(R.id.drag_layer);
mFocusHandler = mDragLayer.getFocusIndicatorHelper();
mWorkspace = mDragLayer.findViewById(R.id.workspace);
mWorkspace.initParentViews(mDragLayer);
mOverviewPanel = findViewById(R.id.overview_panel);
mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
mHotseat = findViewById(R.id.hotseat);
mHotseatSearchBox = findViewById(R.id.search_container_hotseat);
mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mDragLayer.setup(mDragController, mWorkspace);
UiFactory.setOnTouchControllersChangedListener(this, mDragLayer::recreateControllers);
mWorkspace.setup(mDragController);
mWorkspace.lockWallpaperToDefaultPage();
mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */);
mDragController.addDragListener(mWorkspace);
mDropTargetBar = mDragLayer.findViewById(R.id.drop_target_bar);
//获取图标容器
mAppsView = findViewById(R.id.apps_view);
mDragController.setMoveTarget(mWorkspace);
mDropTargetBar.setup(mDragController);
//通过mAllAppsController控制图标
mAllAppsController.setupViews(mAppsView);
}
执行一系列的findViewById操作,找到存储应用图标的容器,将它传递给AllAppsController。
public void setupViews(AllAppsContainerView appsView) {
mAppsView = appsView;
mScrimView = mLauncher.findViewById(R.id.scrim_view);
}
mAppsView 是AllAppsContainerView类型的,它是所有应用程序的视图容器,先看其构造方法。
public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mLauncher = Launcher.getLauncher(context);
mLauncher.addOnDeviceProfileChangeListener(this);
mSearchQueryBuilder = new SpannableStringBuilder();
Selection.setSelection(mSearchQueryBuilder, 0);
mAH = new AdapterHolder[2];
mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);
mNavBarScrimPaint = new Paint();
mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
//界面更新会回调到onAppsUpdated
mAllAppsStore.addUpdateListener(this::onAppsUpdated);
addSpringView(R.id.all_apps_header);
addSpringView(R.id.apps_list_view);
addSpringView(R.id.all_apps_tabs_view_pager);
}
this::onAppsUpdated为OnUpdateListener类型的接口,当应用程序的信息被成功装载到AllAppsStore后,就会刷新界面,回调onAppsUpdated方法。这个方法稍后分析,我们先来看应用程序信息如何被装载的。回到Launcher的OnCreate,LauncherModel调用了startLoader方法。
public boolean startLoader(int synchronousBindPage) {
InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
synchronized (mLock) {
if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
mUiExecutor.execute(oldCallbacks::clearPendingBinds);
stopLoader();
LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
mBgAllAppsList, synchronousBindPage, mCallbacks);
//加载过进入绑定
if (mModelLoaded && !mIsLoaderTaskRunning)
loaderResults.bindWorkspace();
loaderResults.bindAllApps();
loaderResults.bindDeepShortcuts();
loaderResults.bindWidgets();
return true;
} else {
//未加载
startLoaderForResults(loaderResults);
}
}
}
return false;
}
首次进入为未加载状态,因为装载app是一个很耗时的操作,系统将loaderResults放到LoaderTask这个Runnable中执行。
public void startLoaderForResults(LoaderResults results) {
synchronized (mLock) {
stopLoader();
//构建Runnable
mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
启动run方法
runOnWorkerThread(mLoaderTask);
}
}
跟进LoaderTask的run方法中。
public void run() {
synchronized (this) {
if (mStopped) {
return;
}
}
TraceHelper.beginSection(TAG);
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
......
TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
//加载app信息
loadAllApps();
TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
verifyNotStopped();
//绑定数据
mResults.bindAllApps();
......
}
private void loadAllApps() {
final List<UserHandle> profiles = mUserManager.getUserProfiles();
mBgAllAppsList.clear();
for (UserHandle user : profiles) {
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
if (apps == null || apps.isEmpty()) {
return;
}
boolean quietMode = mUserManager.isQuietModeEnabled(user);
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfo app = apps.get(i);
//保存app信息
mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
}
}
if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
for (PackageInstaller.SessionInfo info :
mPackageInstaller.getAllVerifiedSessions()) {
mBgAllAppsList.addPromiseApp(mApp.getContext(),
PackageInstallerCompat.PackageInstallInfo.fromInstallingState(info));
}
}
mBgAllAppsList.added = new ArrayList<>();
}
所有应用程序信息已经加载完成,保存到mBgAllAppsList中。
public void bindAllApps() {
@SuppressWarnings("unchecked")
final ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
Runnable r = new Runnable() {
public void run() {
Callbacks callbacks = mCallbacks.get();
//回调Launcher的bindAllApplications方法
if (callbacks != null) {
callbacks.bindAllApplications(list);
}
}
};
mUiExecutor.execute(r);
}
这里注意到,mBgAllAppsList把应用程序的数据封装成AppInfo类型的,图标的点击事件会根据这个类型进行判断。看到bindAllApps方法,前面分析过,Launcher实现了Callbacks ,这里mBgAllAppsList将数据克隆了一份,通过bindAllApplications方法,传递给了Launcher。
public void bindAllApplications(ArrayList<AppInfo> apps) {
//更新数据到AllAppsStore中
mAppsView.getAppsStore().setApps(apps);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAllApplications(apps);
}
}
AllAppsContainerView中有一个AllAppsStore类型的成员变量,它用来对桌面应用程序信息进行管理,并且当数据更新时通知AllAppsContainerView容器进行刷新。这里的setApps便是向AllAppsStore中更新数据的关键方法。
public class AllAppsStore {
private PackageUserKey mTempKey = new PackageUserKey(null, null);
private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>();
private final List<OnUpdateListener> mUpdateListeners = new ArrayList<>();
private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>();
private boolean mDeferUpdates = false;
private boolean mUpdatePending = false;
//获取应用程序信息集合
public Collection<AppInfo> getApps() {
return mComponentToAppMap.values();
}
public void setApps(List<AppInfo> apps) {
mComponentToAppMap.clear();
//设置当前的应用程序数据
addOrUpdateApps(apps);
}
public void addOrUpdateApps(List<AppInfo> apps) {
//将应用程序信息添加到Map集合中
for (AppInfo app : apps) {
mComponentToAppMap.put(app.toComponentKey(), app);
}
//刷新界面
notifyUpdate();
}
private void notifyUpdate() {
if (mDeferUpdates) {
mUpdatePending = true;
return;
}
int count = mUpdateListeners.size();
//通知AllAppsContainerView刷新界面
for (int i = 0; i < count; i++) {
mUpdateListeners.get(i).onAppsUpdated();
}
}
......
}
AllAppsStore 将数据保存到成员变量mComponentToAppMap中,紧接着我们看到,前面的AllAppsContainerView构造方法设置的监听,onAppsUpdated就在这里被回调了。稍后我们会看到,桌面图标也是通过RecyCleView进行展示的,那么现在数据已经准备完成,就差setAdapter了。
private void onAppsUpdated() {
if (FeatureFlags.ALL_APPS_TABS_ENABLED) {
boolean hasWorkApps = false;
for (AppInfo app : mAllAppsStore.getApps()) {
if (mWorkMatcher.matches(app, null)) {
hasWorkApps = true;
break;
}
}
//把图标数据等,绑定到adapter中
rebindAdapters(hasWorkApps);
}
}
private void rebindAdapters(boolean showTabs) {
rebindAdapters(showTabs, false /* force */);
}
private void rebindAdapters(boolean showTabs, boolean force) {
if (showTabs == mUsingTabs && !force) {
return;
}
replaceRVContainer(showTabs);
mUsingTabs = showTabs;
mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.WORK].recyclerView);
//绑定数据setup
if (mUsingTabs) {
mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkMatcher);
onTabChanged(mViewPager.getNextPage());
} else {
mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
mAH[AdapterHolder.WORK].recyclerView = null;
}
setupHeader();
mAllAppsStore.registerIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
mAllAppsStore.registerIconContainer(mAH[AdapterHolder.WORK].recyclerView);
}
AdapterHolder是AllAppsContainerView的内部类,我们进入看setup绑定数据。
public class AdapterHolder {
public static final int MAIN = 0;
public static final int WORK = 1;
public final AllAppsGridAdapter adapter;
final LinearLayoutManager layoutManager;
final AlphabeticalAppsList appsList;
final Rect padding = new Rect();
AllAppsRecyclerView recyclerView;
boolean verticalFadingEdge;
AdapterHolder(boolean isWork) {
appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore, isWork);
adapter = new AllAppsGridAdapter(mLauncher, appsList);
appsList.setAdapter(adapter);
layoutManager = adapter.getLayoutManager();
}
//设置adapter
void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
appsList.updateItemFilter(matcher);
recyclerView = (AllAppsRecyclerView) rv;
recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
recyclerView.setApps(appsList, mUsingTabs);
recyclerView.setLayoutManager(layoutManager);
//设置adapter
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(null);
FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
recyclerView.addItemDecoration(focusedItemDecorator);
adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
applyVerticalFadingEdgeEnabled(verticalFadingEdge);
applyPadding();
}
在setup中我们看到setAdapter方法了,桌面的图标到这里就全部显示出来。显然,它必须给每个图标设置点击事件,所以我们接着看AllAppsGridAdapter 的onCreateViewHolder方法。
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_ICON:
//图标控件
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
R.layout.all_apps_icon, parent, false);
//桌面图标点击事件
icon.setOnClickListener(ItemClickHandler.INSTANCE);
icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS);
icon.setLongPressTimeout(ViewConfiguration.getLongPressTimeout());
icon.setOnFocusChangeListener(mIconFocusListener);
icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
return new ViewHolder(icon);
......
}
}
viewType有许多类型,桌面图标为VIEW_TYPE_ICON类型,点击事件使用ItemClickHandler将OnClickListener给包装起来。
public class ItemClickHandler {
public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
private static void onClick(View v) {
if (v.getWindowToken() == null) {
return;
}
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!launcher.getWorkspace().isFinishedSwitchingState()) {
return;
}
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v, (ShortcutInfo) tag, launcher);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
//桌面图标为AppInfo类型数据
} else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
}
}
}
//开始Activity的启动
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
Intent intent;
if (item instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
intent = promiseAppInfo.getMarketIntent(launcher);
} else {
intent = item.getIntent();
}
if (intent == null) {
throw new IllegalArgumentException("Input must have a valid intent");
}
if (item instanceof ShortcutInfo) {
ShortcutInfo si = (ShortcutInfo) item;
if (si.hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI)
&& intent.getAction() == Intent.ACTION_VIEW) {
intent = new Intent(intent);
intent.setPackage(null);
}
}
//开始Activity的启动
launcher.startActivitySafely(v, intent, item);
}
}
在前面提到过,桌面图标的应用程序信息都用AppInfo来描述,它包含应用根Activity入口的顾虑条件。因此调用startAppShortcutOrInfoActivity方法,最后再次回到Launcher启动Activity。
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
//调用父类启动Activity
boolean success = super.startActivitySafely(v, intent, item);
if (success && v instanceof BubbleTextView) {
BubbleTextView btv = (BubbleTextView) v;
btv.setStayPressed(true);
setOnResumeCallback(btv);
}
return success;
}
Launcher的父类是BaseDraggingActivity。
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
Bundle optsBundle = useLaunchAnimation
? getActivityLaunchOptionsAsBundle(v)
: null;
......
//开启应用的主入口的activity
startActivity(intent, optsBundle);
} else {
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
getUserEventDispatcher().logAppLaunch(v, intent);
return true;
} catch (ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
}
return false;
}
看到了我们非常熟悉的代码startActivity了,它将启动应用的根Activity,这个方法位于Activity.java中。它的具体调用流程会在《Activity的启动过程》一篇中继续分析。