平台
RK3288 + Android 7.1
问题描述
安装Launcher应用, 并设置为默认主界面, 关机重启后, 无法默认, 仍然弹出选择框.
分析
LOG
//开机后启动的第一个HOME, 是FallbackHome 2019-11-22 15:11:25.542 system_process I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.settings/.FallbackHome} from uid 0 on display 0 2019-11-22 15:11:25.565 system_process I/ActivityManager: Start proc 650:com.android.settings/1000 for activity com.android.settings/.FallbackHome 2019-11-22 15:11:26.158 system_process I/ActivityManager: Displayed com.android.settings/.FallbackHome: +604ms //... 2019-11-22 15:11:27.976 system_process D/ActivityManager: Sending BOOT_COMPLETE user #0 //... 2019-11-22 15:11:28.007 system_process V/PackageManager: Looking for presistent preferred activities... 2019-11-22 15:11:28.007 system_process V/PackageManager: Looking for preferred activities... 2019-11-22 15:11:28.007 system_process V/IntentResolver: Resolving type=null scheme=null defaultOnly=false userId=0 of Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x8 } 2019-11-22 15:11:28.007 system_process V/IntentResolver: Action list: [PreferredActivity{0xa4a6978 com.teslacoilsw.launcher/.NovaLauncher}, null] 2019-11-22 15:11:28.008 system_process V/IntentResolver: Matching against filter PreferredActivity{0xa4a6978 com.teslacoilsw.launcher/.NovaLauncher} 2019-11-22 15:11:28.008 system_process V/IntentResolver: Filter matched! match=0x108000 hasDefault=true 2019-11-22 15:11:28.008 system_process V/IntentResolver: a4a6978 com.teslacoilsw.launcher/.NovaLauncher 2019-11-22 15:11:28.008 system_process V/IntentResolver: mMatch=0x100000 mAlways=true 2019-11-22 15:11:28.008 system_process V/IntentResolver: Selected from: 2019-11-22 15:11:28.008 system_process V/IntentResolver: com.android.launcher3/.Launcher 2019-11-22 15:11:28.008 system_process V/IntentResolver: com.teslacoilsw.launcher/.NovaLauncher 2019-11-22 15:11:28.008 system_process V/IntentResolver: com.android.settings/.FallbackHome 2019-11-22 15:11:28.008 system_process V/IntentResolver: Action: "android.intent.action.MAIN" 2019-11-22 15:11:28.008 system_process V/IntentResolver: Category: "android.intent.category.HOME" 2019-11-22 15:11:28.008 system_process V/IntentResolver: Category: "android.intent.category.DEFAULT" 2019-11-22 15:11:28.008 system_process V/IntentResolver: AutoVerify=false 2019-11-22 15:11:28.008 system_process V/IntentResolver: Final result list: 2019-11-22 15:11:28.008 system_process V/IntentResolver: PreferredActivity{0xa4a6978 com.teslacoilsw.launcher/.NovaLauncher} 2019-11-22 15:11:28.008 system_process V/PackageManager: Figuring out best match... 2019-11-22 15:11:28.008 system_process V/PackageManager: Match for ActivityInfo{2bec482 com.android.launcher3.Launcher}: 0x0 2019-11-22 15:11:28.008 system_process V/PackageManager: Match for ActivityInfo{9a57793 com.teslacoilsw.launcher.NovaLauncher}: 0x108000 2019-11-22 15:11:28.008 system_process V/PackageManager: Match for ActivityInfo{494e3d0 teaonly.rk.droidipcam.CameraActivity}: 0x108000 2019-11-22 15:11:28.008 system_process V/PackageManager: Match for ActivityInfo{3ae8fc9 com.android.settings.FallbackHome}: 0x108000 2019-11-22 15:11:28.011 system_process V/PackageManager: Best match: 0x108000 2019-11-22 15:11:28.011 system_process V/PackageManager: Checking PreferredActivity ds=<none> component=ComponentInfo{com.teslacoilsw.launcher/com.teslacoilsw.launcher.NovaLauncher} 2019-11-22 15:11:28.011 system_process V/PackageManager: Action: "android.intent.action.MAIN" 2019-11-22 15:11:28.011 system_process V/PackageManager: Category: "android.intent.category.HOME" 2019-11-22 15:11:28.011 system_process V/PackageManager: Category: "android.intent.category.DEFAULT" 2019-11-22 15:11:28.011 system_process V/PackageManager: AutoVerify=false 2019-11-22 15:11:28.011 system_process V/PackageManager: Found preferred activity: 2019-11-22 15:11:28.011 system_process V/PackageManager: name=com.teslacoilsw.launcher.NovaLauncher 2019-11-22 15:11:28.011 system_process V/PackageManager: packageName=com.teslacoilsw.launcher 2019-11-22 15:11:28.011 system_process V/PackageManager: enabled=true exported=true directBootAware=false 2019-11-22 15:11:28.011 system_process V/PackageManager: taskAffinity=com.teslacoilsw.launcher.NovaLauncher targetActivity=null persistableMode=PERSIST_ROOT_ONLY 2019-11-22 15:11:28.011 system_process V/PackageManager: launchMode=3 flags=0x3 theme=0x7f0d00f2 2019-11-22 15:11:28.011 system_process V/PackageManager: screenOrientation=5 configChanges=0x203 softInputMode=0x20 2019-11-22 15:11:28.011 system_process V/PackageManager: lockTaskLaunchMode=LOCK_TASK_LAUNCH_MODE_DEFAULT 2019-11-22 15:11:28.011 system_process V/PackageManager: resizeMode=RESIZE_MODE_RESIZEABLE 2019-11-22 15:11:28.011 system_process V/PackageManager: ApplicationInfo: 2019-11-22 15:11:28.011 system_process V/PackageManager: name=com.android.launcher3.LauncherApplication 2019-11-22 15:11:28.011 system_process V/PackageManager: packageName=com.teslacoilsw.launcher 2019-11-22 15:11:28.011 system_process V/PackageManager: labelRes=0x7f0a0060 nonLocalizedLabel=null icon=0x7f030008 banner=0x0 2019-11-22 15:11:28.011 system_process V/PackageManager: className=com.android.launcher3.LauncherApplication 2019-11-22 15:11:28.011 system_process V/PackageManager: processName=com.teslacoilsw.launcher 2019-11-22 15:11:28.011 system_process V/PackageManager: taskAffinity=com.teslacoilsw.launcher 2019-11-22 15:11:28.011 system_process V/PackageManager: uid=10054 flags=0x3 privateFlags=0x800 theme=0x0 2019-11-22 15:11:28.011 system_process V/PackageManager: requiresSmallestWidthDp=0 compatibleWidthLimitDp=0 largestWidthLimitDp=0 2019-11-22 15:11:28.012 system_process V/PackageManager: sourceDir=/data/app/com.teslacoilsw.launcher-1/base.apk 2019-11-22 15:11:28.012 system_process V/PackageManager: seinfo=default 2019-11-22 15:11:28.012 system_process V/PackageManager: dataDir=/data/user/0/com.teslacoilsw.launcher 2019-11-22 15:11:28.012 system_process V/PackageManager: deviceProtectedDataDir=/data/user_de/0/com.teslacoilsw.launcher 2019-11-22 15:11:28.012 system_process V/PackageManager: credentialProtectedDataDir=/data/user/0/com.teslacoilsw.launcher 2019-11-22 15:11:28.012 system_process V/PackageManager: enabled=true minSdkVersion=16 targetSdkVersion=25 versionCode=50102 2019-11-22 15:11:28.012 system_process V/PackageManager: supportsRtl=true 2019-11-22 15:11:28.012 system_process V/PackageManager: fullBackupContent=true //关键LOG, 这里把默认信息删除了. 2019-11-22 15:11:28.012 system_process I/PackageManager: Result set changed, dropping preferred activity for Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x8 } type null 2019-11-22 15:11:28.012 system_process V/PackageManager: Removing preferred activity since set changed ComponentInfo{com.teslacoilsw.launcher/com.teslacoilsw.launcher.NovaLauncher} 2019-11-22 15:11:28.012 system_process V/PackageManager: Preferred activity bookkeeping changed; writing restrictions 2019-11-22 15:11:28.013 com.android.settings D/FallbackHome: User unlocked and real home found; let's go! //再一次查找HOME时, 发现没有了默认信息, 所以显示了选择提示框 2019-11-22 15:11:28.049 system_process I/AccountManagerService: User 0 is unlocked - opening CE database 2019-11-22 15:11:28.056 system_process V/PackageManager: Looking for presistent preferred activities... 2019-11-22 15:11:28.056 system_process V/PackageManager: Looking for preferred activities... 2019-11-22 15:11:28.057 system_process V/IntentResolver: Resolving type=null scheme=null defaultOnly=false userId=0 of Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x108 } 2019-11-22 15:11:28.057 system_process V/IntentResolver: Action list: [PreferredActivity{0xf98a6ce com.teslacoilsw.launcher/.NovaLauncher}, null] 2019-11-22 15:11:28.057 system_process V/IntentResolver: Matching against filter PreferredActivity{0xf98a6ce com.teslacoilsw.launcher/.NovaLauncher} 2019-11-22 15:11:28.057 system_process V/IntentResolver: Filter matched! match=0x108000 hasDefault=true 2019-11-22 15:11:28.057 system_process V/IntentResolver: f98a6ce com.teslacoilsw.launcher/.NovaLauncher 2019-11-22 15:11:28.057 system_process V/IntentResolver: mMatch=0x100000 mAlways=false 2019-11-22 15:11:28.057 system_process V/IntentResolver: Action: "android.intent.action.MAIN" 2019-11-22 15:11:28.057 system_process V/IntentResolver: Category: "android.intent.category.HOME" 2019-11-22 15:11:28.057 system_process V/IntentResolver: Category: "android.intent.category.DEFAULT" 2019-11-22 15:11:28.057 system_process V/IntentResolver: AutoVerify=false 2019-11-22 15:11:28.057 system_process V/IntentResolver: Final result list: 2019-11-22 15:11:28.057 system_process V/IntentResolver: PreferredActivity{0xf98a6ce com.teslacoilsw.launcher/.NovaLauncher} 2019-11-22 15:11:28.057 system_process V/PackageManager: Figuring out best match... 2019-11-22 15:11:28.057 system_process V/PackageManager: Match for ActivityInfo{2bec482 com.android.launcher3.Launcher}: 0x0 2019-11-22 15:11:28.057 system_process V/PackageManager: Match for ActivityInfo{9a57793 com.teslacoilsw.launcher.NovaLauncher}: 0x108000 2019-11-22 15:11:28.057 system_process V/PackageManager: Match for ActivityInfo{494e3d0 teaonly.rk.droidipcam.CameraActivity}: 0x108000 2019-11-22 15:11:28.057 system_process V/PackageManager: Match for ActivityInfo{3ae8fc9 com.android.settings.FallbackHome}: 0x108000 2019-11-22 15:11:28.057 system_process V/PackageManager: Best match: 0x108000 2019-11-22 15:11:28.057 system_process V/PackageManager: Checking PreferredActivity ds=<none> component=ComponentInfo{com.teslacoilsw.launcher/com.teslacoilsw.launcher.NovaLauncher} 2019-11-22 15:11:28.057 system_process V/PackageManager: Action: "android.intent.action.MAIN" 2019-11-22 15:11:28.057 system_process V/PackageManager: Category: "android.intent.category.HOME" 2019-11-22 15:11:28.057 system_process V/PackageManager: Category: "android.intent.category.DEFAULT" 2019-11-22 15:11:28.057 system_process V/PackageManager: AutoVerify=false 2019-11-22 15:11:28.058 system_process V/PackageManager: Skipping mAlways=false entry 2019-11-22 15:11:28.058 system_process V/PackageManager: No preferred activity to return 2019-11-22 15:11:28.058 system_process I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000108 cmp=android/com.android.internal.app.ResolverActivity} from uid 0 on display 0 2019-11-22 15:11:28.058 system_process V/IntentResolver: Resolving type=null scheme=null defaultOnly=false userId=0 of Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000108 cmp=android/com.android.internal.app.ResolverActivity } 2019-11-22 15:11:28.058 system_process V/IntentResolver: Action list: null 2019-11-22 15:11:28.058 system_process V/IntentResolver: Final result list: 2019-11-22 15:11:28.090 ? W/System: ClassLoader referenced unknown path: /system/priv-app/StressTest/lib/arm 2019-11-22 15:11:28.098 system_process I/ActivityManager: Start proc 1076:system:ui/1000 for activity android/com.android.internal.app.ResolverActivity
开机, 第一次启动:
I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME,android.intent.category.DEFAULT] flg=0x10000100 cmp=com.android.settings/.FallbackHome} from uid 0 on display 0
开机完成第一次, 在退出FallbackHome后:
V/IntentResolver: Resolving type=null scheme=null defaultOnly=false userId=0 of Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x8 } //此时因为缺少了CATEGORY_DEFAULT, 所以PM在查找时, 会找到四个, 分别是: Match for ActivityInfo{2bec482 com.android.launcher3.Launcher}: 0x0 Match for ActivityInfo{9a57793 com.teslacoilsw.launcher.NovaLauncher}: 0x108000 Match for ActivityInfo{494e3d0 teaonly.rk.droidipcam.CameraActivity}: 0x108000 Match for ActivityInfo{3ae8fc9 com.android.settings.FallbackHome}: 0x108000
在选择默认时保存的是:
2019-11-23 09:02:38.677 system_process I/PackageManager: Adding preferred activity com.teslacoilsw.launcher/.NovaLauncher for user 0: 2019-11-23 09:02:38.677 system_process I/PackageManager: Action: "android.intent.action.MAIN" 2019-11-23 09:02:38.677 system_process I/PackageManager: Category: "android.intent.category.HOME" 2019-11-23 09:02:38.677 system_process I/PackageManager: Category: "android.intent.category.DEFAULT" 2019-11-23 09:02:38.677 system_process I/PackageManager: AutoVerify=false 2019-11-23 09:02:38.679 system_process I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME,android.intent.category.DEFAULT] flg=0x13000108 cmp=com.teslacoilsw.launcher/.NovaLauncher} from uid 0 on display 0 2019-11-23 09:02:38.679 system_process V/IntentResolver: Resolving type=null scheme=null defaultOnly=false userId=0 of Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME,android.intent.category.DEFAULT] flg=0x13000108 cmp=com.teslacoilsw.launcher/.NovaLauncher } 2019-11-23 09:02:38.679 system_process V/IntentResolver: Action list: null 2019-11-23 09:02:38.679 system_process V/IntentResolver: Final result list:
相关代码如下:
|-- frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent"); if (!sUserManager.exists(userId)) return null; flags = updateFlagsForResolve(flags, userId, intent); enforceCrossUserPermission(Binder.getCallingUid(), userId, false /*requireFullPermission*/, false /*checkShell*/, "resolve intent"); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities"); final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, userId); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); final ResolveInfo bestChoice = chooseBestActivity(intent, resolvedType, flags, query, userId); return bestChoice; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int userId) { if (query != null) { final int N = query.size(); if (N == 1) { return query.get(0); } else if (N > 1) { final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); // If there is more than one activity with the same priority, // then let the user decide between them. ResolveInfo r0 = query.get(0); ResolveInfo r1 = query.get(1); if (DEBUG_INTENT_MATCHING || debug) { Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs " + r1.activityInfo.name + "=" + r1.priority); } // If the first activity has a higher priority, or a different // default, then it is always desirable to pick it. if (r0.priority != r1.priority || r0.preferredOrder != r1.preferredOrder || r0.isDefault != r1.isDefault) { return query.get(0); } // If we have saved a preference for a preferred activity for // this Intent, use that. ResolveInfo ri = findPreferredActivity(intent, resolvedType, flags, query, r0.priority, true, false, debug, userId); if (ri != null) { return ri; } ri = new ResolveInfo(mResolveInfo); ri.activityInfo = new ActivityInfo(ri.activityInfo); ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction()); // If all of the options come from the same package, show the application's // label and icon instead of the generic resolver's. // Some calls like Intent.resolveActivityInfo query the ResolveInfo from here // and then throw away the ResolveInfo itself, meaning that the caller loses // the resolvePackageName. Therefore the activityInfo.labelRes above provides // a fallback for this case; we only set the target package's resources on // the ResolveInfo, not the ActivityInfo. final String intentPackage = intent.getPackage(); if (!TextUtils.isEmpty(intentPackage) && allHavePackage(query, intentPackage)) { final ApplicationInfo appi = query.get(0).activityInfo.applicationInfo; ri.resolvePackageName = intentPackage; if (userNeedsBadging(userId)) { ri.noResourceId = true; } else { ri.icon = appi.icon; } ri.iconResourceId = appi.icon; ri.labelRes = appi.labelRes; } ri.activityInfo.applicationInfo = new ApplicationInfo( ri.activityInfo.applicationInfo); if (userId != 0) { ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(ri.activityInfo.applicationInfo.uid)); } // Make sure that the resolver is displayable in car mode if (ri.activityInfo.metaData == null) ri.activityInfo.metaData = new Bundle(); ri.activityInfo.metaData.putBoolean(Intent.METADATA_DOCK_HOME, true); return ri; } } return null; } ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int priority, boolean always, boolean removeMatches, boolean debug, int userId) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForResolve(flags, userId, intent); // writer synchronized (mPackages) { if (intent.getSelector() != null) { intent = intent.getSelector(); } if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); // Try to find a matching persistent preferred activity. ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query, debug, userId); // If a persistent preferred activity matched, use it. if (pri != null) { return pri; } PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId); // Get the list of preferred activities that handle the intent if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities..."); List<PreferredActivity> prefs = pir != null ? pir.queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId) : null; if (prefs != null && prefs.size() > 0) { boolean changed = false; try { // First figure out how good the original match set is. // We will only allow preferred activities that came // from the same match quality. int match = 0; if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match..."); final int N = query.size(); for (int j=0; j<N; j++) { final ResolveInfo ri = query.get(j); if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Match for " + ri.activityInfo + ": 0x" + Integer.toHexString(match)); if (ri.match > match) { match = ri.match; } } if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Best match: 0x" + Integer.toHexString(match)); match &= IntentFilter.MATCH_CATEGORY_MASK; final int M = prefs.size(); for (int i=0; i<M; i++) { final PreferredActivity pa = prefs.get(i); if (DEBUG_PREFERRED || debug) { Slog.v(TAG, "Checking PreferredActivity ds=" + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>") + "\n component=" + pa.mPref.mComponent); pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); } if (pa.mPref.mMatch != match) { if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping bad match " + Integer.toHexString(pa.mPref.mMatch)); continue; } // If it's not an "always" type preferred activity and that's what we're // looking for, skip it. if (always && !pa.mPref.mAlways) { if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry"); continue; } final ActivityInfo ai = getActivityInfo( pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId); if (DEBUG_PREFERRED || debug) { Slog.v(TAG, "Found preferred activity:"); if (ai != null) { ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " "); } else { Slog.v(TAG, " null"); } } if (ai == null) { // This previously registered preferred activity // component is no longer known. Most likely an update // to the app was installed and in the new version this // component no longer exists. Clean it up by removing // it from the preferred activities list, and skip it. Slog.w(TAG, "Removing dangling preferred activity: " + pa.mPref.mComponent); pir.removeFilter(pa); changed = true; continue; } for (int j=0; j<N; j++) { final ResolveInfo ri = query.get(j); if (!ri.activityInfo.applicationInfo.packageName .equals(ai.applicationInfo.packageName)) { continue; } if (!ri.activityInfo.name.equals(ai.name)) { continue; } if (removeMatches) { pir.removeFilter(pa); changed = true; if (DEBUG_PREFERRED) { Slog.v(TAG, "Removing match " + pa.mPref.mComponent); } break; } // Okay we found a previously set preferred or last chosen app. // If the result set is different from when this // was created, we need to clear it and re-ask the // user their preference, if we're looking for an "always" type entry. if (always && !pa.mPref.sameSet(query)) { Slog.i(TAG, "Result set changed, dropping preferred activity for " + intent + " type " + resolvedType); if (DEBUG_PREFERRED) { Slog.v(TAG, "Removing preferred activity since set changed " + pa.mPref.mComponent); } pir.removeFilter(pa); // Re-add the filter as a "last chosen" entry (!always) PreferredActivity lastChosen = new PreferredActivity( pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false); pir.addFilter(lastChosen); changed = true; return null; } // Yay! Either the set matched or we're looking for the last chosen if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: " + ri.activityInfo.packageName + "/" + ri.activityInfo.name); return ri; } } } finally { if (changed) { if (DEBUG_PREFERRED) { Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions"); } scheduleWritePackageRestrictionsLocked(userId); } } } } if (DEBUG_PREFERRED || debug) Slog.v(TAG, "No preferred activity to return"); return null; }
原因与解决方案
分解下出问题时的步骤:
安装新的Launcher
点击HOME键, 并从列表中选择一个默认为默认
重启主板
主板显示列表选择框.
出现问题的地方在第4步
从上面的LOG可以看出, 设置默认时的信息是: act=android.intent.action.MAIN cat=[android.intent.category.HOME,android.intent.category.DEFAULT]
在重启后, 过入了FallbackHome, 在FallbackHome有以下代码调用PM的resolveActivity方法, 而此方法传入的Intent为
act=android.intent.action.MAIN cat=[android.intent.category.HOME]: private void maybeFinish() { if (getSystemService(UserManager.class).isUserUnlocked()) { final Intent homeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME); final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0); if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) { Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?"); mHandler.sendEmptyMessageDelayed(0, 200); } else { Log.d(TAG, "User unlocked and real home found; let's go!"); getSystemService(PowerManager.class).userActivity( SystemClock.uptimeMillis(), false); finish(); } } }
在FallbackHome执行完后, PM会删除默认信息: PackageManager: Removing preferred activity since set changed ComponentInfo{com.teslacoilsw.launcher/com.teslacoilsw.launcher.NovaLauncher}
删除默认信息后, 当FallbackHome finish自己后, 系统重新startHome时, 就会出现, 未找到默认, 并显示列表选择框
启动后, 第一个进入的Launcher是 Settings中的 FallbackHome, 在启动初始化完成后, FallbackHome会Finsish自己, 并交由系统去启动新的Launcher.
问题出现时, 在PM中查找Launcher的数量与之前设置默认时不一致:
第一次是4个:
{ActivityInfo{da70dd6 com.android.launcher3.Launcher}} {ActivityInfo{fdc4857 com.teslacoilsw.launcher.NovaLauncher}} {ActivityInfo{91f7f44 teaonly.rk.droidipcam.CameraActivity}} {ActivityInfo{6138c45 com.android.settings.FallbackHome}}
在后面选择了默认后, 是3个:
{ActivityInfo{da70dd6 com.android.launcher3.Launcher}} {ActivityInfo{fdc4857 com.teslacoilsw.launcher.NovaLauncher}} {ActivityInfo{6138c45 com.android.settings.FallbackHome}}
多出来的一个 CameraActivity定义如下(缺少了category.DEFAULT):
<activity android:name="teaonly.rk.droidipcam.CameraActivity" android:label="@string/app_name" android:screenOrientation="landscape" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
之所有会出现数量上的差别, 是由于在调用PM的resolveIntent遍历时, 有两个相关的因素:
传去的FLAG不同: PackageManager.MATCH_DEFAULT_ONLY(0x00010000)
Intent中带的信息不同.
解决方案:
1
1.1 修改 FallbackHome 的 maybeFinish函数
private void maybeFinish() { if (getSystemService(UserManager.class).isUserUnlocked()) { final Intent homeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME). //添加DEFAULT使Intent保持与保存默认的信息一致 .addCategory(Intent.CATEGORY_DEFAULT); //... } }
1.2 同样修改 FallbackHome 的 maybeFinish函数
private void maybeFinish() { //... //0 -> android.content.pm.PackageManager.MATCH_DEFAULT_ONLY final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, android.content.pm.PackageManager.MATCH_DEFAULT_ONLY); //... }
PS 1/2 的方法需配合修改:
|–frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
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); //添加DEFAULT intent.addCategory(Intent.CATEGORY_DEFAULT); } return intent; }
2
在PM中强制为Launcher的过滤添加 DEFAULT
--- a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4830,6 +4830,14 @@ public class PackageManagerService extends IPackageManager.Stub { } } + //AnsonCode + boolean isHome(Intent intent){ + if(intent != null && intent.getCategories() != null){ + return intent.getAction().equals(Intent.ACTION_MAIN) && intent.getCategories().contains(Intent.CATEGORY_HOME); + } + return false; + } + @Override public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { @@ -4842,6 +4850,10 @@ public class PackageManagerService extends IPackageManager.Stub { false /*requireFullPermission*/, false /*checkShell*/, "resolve intent"); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities"); + //AnsonCode + if(isHome(intent)){ + flags |= PackageManager.MATCH_DEFAULT_ONLY; + } final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, userId); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
扩展
FallbackHome 与 Launcher
FallbackHome的注册信息:
<activity android:name=".FallbackHome" android:excludeFromRecents="true" android:screenOrientation="nosensor" android:theme="@style/FallbackHome"> <intent-filter android:priority="-1000"> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
Launcher的注册信息:
<activity android:name="com.android.launcher3.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:theme="@style/LauncherTheme" android:windowSoftInputMode="adjustPan" android:configChanges="keyboard|keyboardHidden|navigation" android:resumeWhilePausing="true" android:taskAffinity="" android:enabled="true"> <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>
启动的顺序:
2019-11-22 14:55:32.453 system_process I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.settings/.FallbackHome} from uid 0 on display 0 2019-11-22 14:55:35.073 system_process I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher} from uid 0 on display 0
首先, FallbackHome的优先级是比较低的, 但反而是先于launcher启动, 主要是由于Settings中有 android:directBootAware="true"的定义,
参见android 7.1 缺少设置directBootAware导致无法启动指定Launcher
偏好activity储存位置: ./system/users/0/package-restrictions.xml