平台
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