该文章解说下Launcher启动相干常识,并更正网上某些文章的谬误点.
本篇为鸡生蛋系列第五篇文章, 也即最初篇, 终于能够完结该系列了。
- Linux input零碎数据上报流程
- Android InputManager剖析
- AMS startActivity()
- activity显示过程梳理
- HomeLauncher启动
[代码: Android 11]
http://aosp.opersys.com/xref/…
[代码: Android 8.1]
http://aosp.opersys.com/xref/…
startHomeActivityLocked()
搜网上材料, 好些文章说launcher启动是在
ActivityManagerService.systemReady() --> startHomeActivityLocked()
时启动的, 那这个对不对呢? 这个其实对,也不对,(也可能是他们剖析的版本太老了吧)。
说它不对咱们前面点再说, 先简略看下这个流程代码。
AMS(ActivityManagerService) systemReady()是在SystemServer startOtherServices()时调用的, 其过程整顿如下:
frameworks/base/services/java/com/android/server/SystemServer.java
main(String[] args)
+ new SystemServer().run();
+ startBootstrapServices(t);
+ startCoreServices(t);
+ startOtherServices(t);
+ mActivityManagerService.systemReady(() -> {
......// callback参数会里启动system ui, 有须要的可关注下
startSystemUi(context, windowManagerF);
......
)
对于 < Android10的版本, AMS的systemReady()进一步通过 startHomeActivityLocked(), 好些文章认为在此就启动了launcher
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
......
startHomeActivityLocked(currentUserId, "systemReady");
boolean startHomeActivityLocked(int userId, String reason) {
......
// home intent
Intent intent = getHomeIntent();
// 失去该intent应该启哪个利用
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
......
// 启动该activity, 前面流程和利用启动流程差不多,就不说了
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
具体的代码解说可网上搜下相干文章, 网上有很多,
好,
<big>完!</big>
可是…
事件真的完了吗?
我之前也始终认为是这样的, 我想着他人都写了一大堆这类文章,多我一个也没啥意思,所以就想用逆向剖析的办法来看看,后果这一剖析,发现有些不对的中央.
逆向剖析
所谓逆向剖析,就是我假如我不晓得答案,也不太分明framework咋玩的,从launcher的onCreate()动手,看能不能失去雷同的后果.
所采纳的办法呢,也很简略,也就是打印调用堆栈,而后看代码持续剖析,持续打印调用堆栈….反复
具体的说,安卓java层常见的打印堆栈办法有如下几种:
- Throwable
Log.i(TAG, Log.getStackTraceString(new Throwable()));
- Exception
Exception e = new Exception("testandroid this is a log");
e.printStackTrace();
也即简化为
new Exception("testandroid this is a log").printStackTrace();
- RuntimeException
RuntimeException callStack = new RuntimeException("callstack: ");
callStack.fillInStackTrace();
Log.e(TAG, "testandroid this is a log: ", callStack);
那咱们就实战一把, 先在Launcher里加上log,
留神:
我实战用的代码为android8.1的源码, 因为我目前就只有该平台的开发机.
堆栈也不重要, 看下分析方法就行.
/home/atom/work/code/suiren_master/LINUX/android/packages/apps/Launcher3
@@ -350,6 +350,13 @@ public class Launcher extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
+ RuntimeException callStack = new RuntimeException("callstack: ");
+ callStack.fillInStackTrace();
+ Log.e(TAG,"testandroid this is a log: ", callStack);
打印出的堆栈如下:
Launcher: testandroid this is a log:
Launcher: java.lang.RuntimeException: callstack:
Launcher: at com.android.launcher3.Launcher.onCreate(Launcher.java:354)
Launcher: at android.app.Activity.performCreate(Activity.java:7082)
Launcher: at android.app.Activity.performCreate(Activity.java:7073)
Launcher: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
Launcher: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2737)
Launcher: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862)
Launcher: at android.app.ActivityThread.-wrap11(Unknown Source:0)
Launcher: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1595)
Launcher: at android.os.Handler.dispatchMessage(Handler.java:106)
Launcher: at android.os.Looper.loop(Looper.java:164)
// ActivityThread.main()函数, 通过AMS startActivity()章节剖析可晓得其通过zyogote fork后会调用该函数
Launcher: at android.app.ActivityThread.main(ActivityThread.java:6524)
Launcher: at java.lang.reflect.Method.invoke(Native Method)
Launcher: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
Launcher: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
后果加了第一个log,就发现了些问题,
问题1:
因为咱们代码是有开机向导的,后果发现要开机向导完结后才调用Launcher的onCreate()
我在AMS startHomeActivityLocked()也加了log, systemReady()时的确是有调用到, 然而没有Launcher的onCreate(), 问题1之后才有
我先把逆向剖析讲完再回头看这两问题
从下面堆栈看, 利用调到了ActivityThread.main(), 如果再沿着这个剖析可能就很难了,这个就须要点背景常识了.
在剖析AMS startActivity()时咱们晓得, 利用会通过zygoteProcess.start()申请zyogote fork利用,
frameworks/base/core/java/android/os/Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
......) {
// 留神 processClass 为 "android.app.ActivityThread"
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
strat()会进一部调用startViaZygote(), 咱们调加启动利用流程调用栈应该在如下中央
frameworks/base/services/core/java/android/os/ZygoteProcess.java
private Process.ProcessStartResult startViaZygote(final String processClass,....
+ RuntimeException callStack = new RuntimeException("callstack: ");
+ callStack.fillInStackTrace();
// 将niceName打印进去不便看启动哪个利用
+ Log.e(LOG_TAG, "testandroid this is a log: " + processClass + " niceName:" + niceName + " ", callStack);
其堆栈如下
// com.android.launcher3 启动
ZygoteProcess: testandroid this is a log: android.app.ActivityThread niceName:com.android.launcher3
ZygoteProcess: java.lang.RuntimeException: callstack:
ZygoteProcess: at android.os.ZygoteProcess.startViaZygote(ZygoteProcess.java:346)
ZygoteProcess: at android.os.ZygoteProcess.start(ZygoteProcess.java:208)
ZygoteProcess: at android.os.Process.start(Process.java:462)
ZygoteProcess: at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4007)
ZygoteProcess: at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3829)
ZygoteProcess: at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3715)
ZygoteProcess: at com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked(ActivityStackSupervisor.java:1599)
ZygoteProcess: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2755)
ZygoteProcess: at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2268)
ZygoteProcess: at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2102)
ZygoteProcess: at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1499)
ZygoteProcess: at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:1426)
// activityPaused
ZygoteProcess: at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:7691)
// binder通信, 调用栈断了
ZygoteProcess: at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:317)
ZygoteProcess: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2980)
这里onTransactd()是binder通信, 所以须要晓得binder proxy侧谁调用该binder函数, 而后在那儿增加日志
通过搜代码,还好,就一个中央, 能够在该中央加上日志
frameworks/base/core/java/android/app/ActivityThread.java
private void handlePauseActivity(IBinder token, boolean finished,....
......
// 调用activityPaused(), 可在此加上日志,
ActivityManager.getService().activityPaused(token);
因为两头有handler也会导致栈信息断, 对handler message这种导致的栈断只能剖析代码看谁在sendMessage()给它了
具体过程了加的日志就不说了, 其流程为 schedulePauseActivity() --> sendMessage(PAUSE_ACTIVITY_FINISHING/PAUSE_ACTIVITY) --> handlePauseActivity() --> ActivityManager.getService().activityPaused(token);
进一步的堆栈如下:
// 其是通过 ActivityStack.java schedulePauseActivity 调用到了
ActivityManager: testandroid ActivityStack.java schedulePauseActivity java.lang.Throwable
ActivityManager: at com.android.server.am.ActivityStack.startPausingLocked(ActivityStack.java:1359)
ActivityManager: at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:3821)
ActivityManager: at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:3763)
ActivityManager: at com.android.server.am.ActivityStack.requestFinishActivityLocked(ActivityStack.java:3611)
// 谁在调用finishActivity() ?
ActivityManager: at com.android.server.am.ActivityManagerService.finishActivity(ActivityManagerService.java:5283)
堆栈的最初为 finishActivity()
, 那么谁在调用呢?
调用finishActivity()的中央也有好几个,可在各个中央加上代码, 最终是在 Activity.java finish() 调用的
代码如下:
frameworks/base/core/java/android/app/Activity.java
private void finish(int finishTask) {
......
if (ActivityManager.getService()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
堆栈如下:
Activity.java finish()
System.err: java.lang.Exception: testandroid Activity.java finish
System.err: at android.app.Activity.finish(Activity.java:5562)
System.err: at android.app.Activity.finish(Activity.java:5600)
System.err: at com.android.settings.FallbackHome.maybeFinish(FallbackHome.java:129)
System.err: at com.android.settings.FallbackHome.-wrap0(Unknown Source:0)
System.err: at com.android.settings.FallbackHome$1.onReceive(FallbackHome.java:106)
至此, 咱们终于看到了, 是在 FallbackHome onReceive() 时调用了finish(), 而后才把launcher启动起来.
那咱们看下代码(剖析看正文):
packages/apps/Settings/src/com/android/settings/FallbackHome.java
protected void onCreate(Bundle savedInstanceState) {
......
// 注册了用户解锁的 receiver
registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
// 留神这里的maybeFinish并没有调起launcher
maybeFinish();
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 接到用户解锁,而后调maybeFinish()
maybeFinish();
}
};
private void maybeFinish() {
// 用户是否解锁, 如果onCreate()-->maybeFinish()时如果用户没解锁则啥也不做
if (getSystemService(UserManager.class).isUserUnlocked()) {
final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME);
......
Log.d(TAG, "User unlocked and real home found; let's go!");
getSystemService(PowerManager.class).userActivity(
SystemClock.uptimeMillis(), false);
// 调用finish完结本人activity
finish();
}
}
}
这时候事件进一步明了了,
FallbackHome onReceive() 接到用户解锁播送时调用了finish(),本人的activity退出时才把launcher启动
那 startHomeActivityLocked() 是不是在Launcher启动时就齐全没作用呢?
发现有日志:
ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher} from uid 0
而后找到代码所在中央,通过打印堆栈发现其实是有调用的.
ActivityManager: ActivityStarter.java testandroid this is a log:
ActivityManager: java.lang.RuntimeException: callstack:
ActivityManager: at com.android.server.am.ActivityStarter.startActivity(ActivityStarter.java:331)
ActivityManager: at com.android.server.am.ActivityStarter.startActivityLocked(ActivityStarter.java:283)
ActivityManager: at com.android.server.am.ActivityStarter.startHomeActivityLocked(ActivityStarter.java:655)
ActivityManager: at com.android.server.am.ActivityManagerService.startHomeActivityLocked(ActivityManagerService.java:4241)
ActivityManager: at com.android.server.am.ActivityStackSupervisor.resumeHomeStackTask(ActivityStackSupervisor.java:781)
ActivityManager: at com.android.server.am.ActivityStack.resumeTopActivityInNextFocusableStack(ActivityStack.java:2779)
ActivityManager: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2326)
ActivityManager: at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2268)
ActivityManager: at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2107)
ActivityManager: at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2091)
ActivityManager: at com.android.server.am.ActivityStack.finishCurrentActivityLocked(ActivityStack.java:3943)
ActivityManager: at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1458)
ActivityManager: at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:1426)
ActivityManager: at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:7686)
ActivityManager: at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:317)
ActivityManager: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2980)
Provision
让咱们回到问题1
因为咱们代码是有开机向导的,后果发现要开机向导完结后才调用Launcher的onCreate()
Android默认的开机向导为 Provision, 其代码也很简略, 次要为
设置一些数据库值 –> 把本人disable, 之后home intent时就不会找到本人了 –> 完结本人
packages/apps/Provision/src/com/android/provision/DefaultActivity.java
protected void onCreate(Bundle icicle) {
......
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.TV_USER_SETUP_COMPLETE, 1);
// remove this activity from the package manager.
// disable该activity
PackageManager pm = getPackageManager();
ComponentName name = new ComponentName(this, DefaultActivity.class);
pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
// terminate the activity.
// 完结该activity
finish();
}
HOME intent优先级问题
AMS systemReady() –> startHomeActivityLocked() 时获取到的为 FallbackHome
boolean startHomeActivityLocked(int userId, String reason) {
// 取得home intent
Intent intent = getHomeIntent();
// 失去该intent应该启哪个利用
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
......
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
日志(零碎里还有别的响应home的activity, 这里就没列出了,次要看这三个):
ActivityManager: startHomeActivityLocked ?? act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.settings/.FallbackHome
// 开机向导设置完之后DefaultActivity会禁用,之后启机不会再匹配上
ActivityManager: startHomeActivityLocked ?? act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.provision/.DefaultActivity
ActivityManager: startHomeActivityLocked ?? act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher
可是看了其优先级设置,
packages/apps/Settings/AndroidManifest.xml
<activity android:name=".FallbackHome"
...... // FallbackHome 优先级 -1000
<intent-filter android:priority="-1000">
packages/apps/Provision/AndroidManifest.xml
<activity android:name="DefaultActivity"
......// DefaultActivity 优先级 3
<intent-filter android:priority="3">
FallbackHome 优先级 -1000, 为最小
DefaultActivity 优先级 3
Launcher3 没有设置
实践上来说,有开机向导时,应该 DefaultActivity 匹配上, 之后重启应该是 Launcher3 匹配上,
那么为啥systemReady()时为FallbackHome, 或者说为啥老是 FallbackHome 先匹配上?
按理来说其优先级最低,应该最初匹配上才对啊.
resolveActivityInfo()流程如下:
resolveActivityInfo() / ActivityManagerService.java
+ AppGlobals.getPackageManager().resolveIntent()
+ resolveIntent() / PackageManagerService.java
+ resolveIntentInternal()
+ queryIntentActivitiesInternal() // 查问所有符合条件的activities
| + result = filterIfNotSystemUser(mActivities.queryIntent(.....))
| + super.queryIntent(....) / class ActivityIntentResolver
| + buildResolveList(....firstTypeCut, finalList, userId); / IntentResolver.java
+ chooseBestActivity() // 抉择最好的那个
在下面流程中,会先查问出所有符合条件的activities, 而后选出最好的那个, 有须要的能够在这儿查看选取规定.
本认为是chooseBestActivity()时DefaultActivity/Launcher3不是最好的, 加上log确认原来在 queryIntentActivitiesInternal() 时最开始就只有 FallbackHome
间接启动
buildResolveList()之后可简略看看调查过程和正文, 因为代码老是变,也没多大意义, 次要的是提下前面的调查结果和发现了 间接启动 这么个对我来说的新货色.
frameworks/base/services/core/java/com/android/server/IntentResolver.java
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
boolean debug, boolean defaultOnly, String resolvedType, String scheme,
F[] src, List<R> dest, int userId) {
......
match = filter.match(action, resolvedType, scheme, data, categories, TAG);
if (match >= 0) {
// 关上这里的日志发现其实最后时 FallbackHome DefaultActivity Launcher 都有match的
if (debug) Slog.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match) + " hasDefault="
+ filter.hasCategory(Intent.CATEGORY_DEFAULT));
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
// 然而后两者返回的为null
final R oneResult = newResult(filter, match, userId);
if (oneResult != null) {
// 如果不为null才退出到dest里
dest.add(oneResult);
newResult 对于activity intent来说实现在
PackageManagerService.java
......
final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
int match, int userId) {
if (!sUserManager.exists(userId)) return null;
// 这里返回为null, 因为DefaultActivity设置后会把本人禁用, 所以重启时他没匹配上倒也能够了解,
// 可是为啥起机后 Launcher 也在 FallbackHome 后匹配上呢? 能够持续考察
if (!mSettings.isEnabledAndMatchLPr(info.activity.info, mFlags, userId)) {
return null;
}
frameworks/base/services/core/java/com/android/server/pm/Settings.java
boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
final PackageSetting ps = mPackages.get(componentInfo.packageName);
if (ps == null) return false;
final PackageUserState userState = ps.readUserState(userId);
// 这里反回false
return userState.isMatch(componentInfo, flags);
}
frameworks/base/core/java/android/content/pm/PackageUserState.java
public boolean isMatch(ComponentInfo componentInfo, int flags) {
final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp();
final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
if (!isAvailable(flags)
&& !(isSystemApp && matchUninstalled)) return false;
// Enable判断
if (!isEnabled(componentInfo, flags)) return false;
if ((flags & MATCH_SYSTEM_ONLY) != 0) {
if (!isSystemApp) {
return false;
}
}
final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
&& !componentInfo.directBootAware;
final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
&& componentInfo.directBootAware;
// 对Launcher来说, 这里起机时刚开始反回false, 之后返回true
return matchesUnaware || matchesAware;
}
看到最初 DIRECT_BOOT_UNAWARE DIRECT_BOOT_AWARE componentInfo.directBootAwar 这是啥呢?
这个其实就是对间接启动利用判断,
间接启动材料可看:
https://developer.android.goo…
简略说就是未解锁时能够运行的程序,比如说未解锁拍照.
FallbackHome 所在的设置是有反对间接启动, Launcher 不反对, 所以FallbackHome总是会先匹配, 解锁后Launcher才有机会匹配上.
packages/apps/Settings/AndroidManifest.xml
<application android:label="@string/settings_label"
...// FallbackHome 所在的设置反对间接启动
android:directBootAware="true">
总结
- 对home intent的响应是有优先级的, 所以AMS systemReady()调用 start home时并不一定会启动launcher, 当其它优先级的home activity响应完后才有可能是 launcher
- 一般说来, launcher启动是在, settings FallbackHome 监听到解锁后调用finish() 完结本人时,才把launcher启动起来
- 因为 settings 反对 间接启动, launcher 不反对, 所以未解锁时launcher不会匹配到home intent.
- 一些home intent的优先级
package activity | 优先级 |
---|---|
com.android.settings CryptKeeper | 10 |
com.android.provision DefaultActivity | 3 |
com.android.launcher3 Launcher | 默认 |
com.android.settings FallbackHome | -1000 |
- Android 11 AMS systemRead() startHomeOnDisplay() 流程简略整顿:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
+ // goingCallback 回调, 这里会启动systemui
| if (goingCallback != null) goingCallback.run();
+ // start user
| mSystemServiceManager.startUser(t, currentUserId);
+ // 启动persistent利用
| startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ // 启动所有屏的 Home,
| mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
| // mAtmInternal为ActivityTaskManagerInternal类型,其最终实现在
| // ActivityTaskManagerService.java
+ // final class LocalService extends ActivityTaskManagerInternal
+ mRootWindowContainer.startHomeOnDisplay(...) / ActivityTaskManagerService.java
+ startHomeOnTaskDisplayArea(...) / RootWindowContainer.java
+ if (taskDisplayArea == getDefaultTaskDisplayArea()) {
| homeIntent = mService.getHomeIntent();
| // 失去默认屏home intent的activity
| aInfo = resolveHomeActivity(userId, homeIntent);
| } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
| // 失去第二个屏home intent的activity
| Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
+
+ mService.getActivityStartController().startHomeActivity(...)
+
| ActivityStartController.java
| void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
| TaskDisplayArea taskDisplayArea) {...
| // 多屏相干, 启动到哪个屏设置
| final int displayId = taskDisplayArea.getDisplayId();
| options.setLaunchDisplayId(displayId);
| options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken
| .toWindowContainerToken());
| ......
|
| mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
| .setOutActivity(tmpOutRecord)
| .setCallingUid(0)
| .setActivityInfo(aInfo)
| .setActivityOptions(options.toBundle())
+ .execute();
发表回复