Android 7.1设置默认Launcher重启后失效(需手动选择)

简介: Android 7.1设置默认Launcher重启后失效(需手动选择)

平台


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


相关文章
|
3月前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
119 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
2月前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
246 3
|
3月前
|
Java 网络安全 开发工具
UNITY与安卓⭐一、Android Studio初始设置
UNITY与安卓⭐一、Android Studio初始设置
|
4月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
103 12
|
2月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
150 0
|
3月前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
27 0
|
3月前
|
数据可视化 Java 数据挖掘
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
33 0
|
4月前
|
Java Android开发
android 设置系统时间的流程
android 设置系统时间的方法
347 2
|
5月前
|
Android开发
Android Studio(2022.3.1)设置阿里云源-新旧版本
Android Studio(2022.3.1)设置阿里云源-新旧版本
1074 1
|
5月前
|
XML Java Android开发
Android RecyclerView用代码动态设置item的selector
Android RecyclerView用代码动态设置item的selector
41 0