Android launcher应用启动过程(基于Android 11)

3,608 阅读8分钟

参考链接

  1. Android系统启动流程之init进程启动

前言

本篇基于Android11源码分析系统中桌面应用的启动过程。 在Android 系统中,桌面其本质也只是一个系统应用。下文,我们分析 launcher启动过程。 首先,我们从 package-restrications.xml 偏好文件讲起.

配置默认启动桌面

package-restrications.xml 介绍

package-restrications.xml 文件,位于/data/system/users/0/package-restrictions.xml,文件中保存了一些关于应用状态(应用是否被禁用),应用偏好信息。其中包括桌面应用信息,默认桌面的配置信息。

<package-restrictions>
    ...
    <preferred-activities>
     ...
     <item name="com.my.launcher/.activity.MainActivity" match="100000" always="true" set="3">
            <set name="com.android.launcher3/.uioverrides.QuickstepLauncher" />
            <set name="com.my.launcher/.activity.MainActivity" />
            <set name="com.android.settings/.FallbackHome" />
            <filter>
                <action name="android.intent.action.MAIN" />
                <cat name="android.intent.category.HOME" />
                <cat name="android.intent.category.DEFAULT" />
            </filter>
        </item>
    </preferred-activities>
    <persistent-preferred-activities />
    ...
</package-restrictions>

preferred-activities 下保存了应用偏好,filter 标签下的广播和cat 就是用于判断是否是桌面应用Activity的。

系统启动后,如果用户手动修改了应用的状态或者偏好,package-restrictions.xml 会被重写为当前系统配置。如果用户没有涉及的操作,在关机时该文件也并不会被重写。

桌面应用的开发

在应用的Activity进行如下配置,该应用就是桌面应用了,按下home键,会提示你选择桌面。

image.png

但是,大多厂商会都是要求三方页面是经过他们认证的,才可以设置。比如我的小米手机,就禁止设置非认证 的三方桌面。 4458358216cc3d8be6bb220c29c7309.jpg

系统启动

此处只从 Java 层开始分析,init 进程启动了ZygoteInit 进程。 在 frameworks/base/core/java/com/android/internal/os/ZygoteInit.javamain方法中,调用了forkSystemServer 方法,启动了SystemServer 进程。

SystemService.java

public static void main(String[] args) {
    new SystemServer().run();
}
private void run(){
    ...
    startBootstrapServices(t);
    startCoreServices(t);
    startOtherServices(t);
    ...
}
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    
    ...
    // 启动AMS
    t.traceBegin("StartActivityManager");
    // TODO: Might need to move after migration to WM.
    ActivityTaskManagerService atm = mSystemServiceManager.startService(
            ActivityTaskManagerService.Lifecycle.class).getService();
    mActivityManagerService = ActivityManagerService.Lifecycle.startService(
            mSystemServiceManager, atm);
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    mWindowManagerGlobalLock = atm.getGlobalLock();
    t.traceEnd();
    ...
    // 启动PMS
    t.traceBegin("StartPackageManagerService");
    try {
        Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    } finally {
        Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
    }

    // Now that the package manager has started, register the dex load reporter to capture any
    // dex files loaded by system server.
    // These dex files will be optimized by the BackgroundDexOptService.
    SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);

    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    t.traceEnd();
    ...
}    
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
      mActivityManagerService.systemReady(() -> {
      },t);

}

如上代码所示,SystemServer 进程启动后调用了其run方法,run 方法中依次调用了 startBootstrapServicesstartCoreServicesstartOtherServices

startBootstrapServices 方法中,启动了 ActivityManagerServicePackageManagerService 等服务。 startCoreServices 中启动了 电池管理,用户状态以及其他核心服务。同时对ActivityManagerServicePackageManagerService 也做了一些操作.

读取package-restrications.xml配置

启动 PMS ,创建一个 PackageManagerService对象。而在PackageManagerService 的构造方法中,会读取package-restrications.xml配置。

PackageManagerService

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
    ...
    t.traceBegin("read user settings");
    //代码1
    mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));
    t.traceEnd();
    ...
}
  • 代码1 调用 Settings.readLPw 方法,读取用户的设置。 frameworks/base/services/core/java/com/android/server/pm/Settings.java
boolean readLPw(@NonNull List<UserInfo> users) {
    ...
    for (UserInfo user : users) {
        readPackageRestrictionsLPr(user.id);
    }
    ...
}
void readPackageRestrictionsLPr(int userId) {
    PackageSetting ps = null;
    while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
           && (type != XmlPullParser.END_TAG
                   || parser.getDepth() > outerDepth)) {
        if (type == XmlPullParser.END_TAG
                || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals(TAG_PACKAGE)) {//"pkg"
            //代码2 读取应用的相关信息
            ...
        } else if (tagName.equals("preferred-activities")) {
            //代码3 读取偏好实则
            readPreferredActivitiesLPw(parser, userId);
        } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
            readPersistentPreferredActivitiesLPw(parser, userId);
        } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
            readCrossProfileIntentFiltersLPw(parser, userId);
        } else if (tagName.equals(TAG_DEFAULT_APPS)) {
            readDefaultAppsLPw(parser, userId);
        } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
            readBlockUninstallPackagesLPw(parser, userId);
        } else {
            Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                  + parser.getName());
            XmlUtils.skipCurrentTag(parser);
        }
    }
}
  • 代码1 调用readPackageRestrictionsLPr 方法,读取 package-restrications.xml 配置
  • 代码2 读取应用的信息,包括应用状态,是否被禁用等
  • 代码3 读取应用的偏好,其中就包括了默认桌面项(如果是第一次开机,没有配置,则没有桌面偏好项)
void readPreferredActivitiesLPw(XmlPullParser parser, int userId)
        throws XmlPullParserException, IOException {
    int outerDepth = parser.getDepth();
    int type;
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals(TAG_ITEM)) {
            PreferredActivity pa = new PreferredActivity(parser);
            if (pa.mPref.getParseError() == null) {
                
                final PreferredIntentResolver resolver = editPreferredActivitiesLPw(userId);
                ArrayList<PreferredActivity> pal = resolver.findFilters(pa);
                //代码1
                if (pal == null || pal.size() == 0 || pa.mPref.mAlways) {
                    resolver.addFilter(pa);
                }
            } else {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Error in package manager settings: <preferred-activity> "
                                + pa.mPref.getParseError() + " at "
                                + parser.getPositionDescription());
            }
        } else {
            PackageManagerService.reportSettingsProblem(Log.WARN,
                    "Unknown element under <preferred-activities>: " + parser.getName());
            XmlUtils.skipCurrentTag(parser);
        }
    }
}

PreferredIntentResolver editPreferredActivitiesLPw(int userId) {
    //代码3
    PreferredIntentResolver pir = mPreferredActivities.get(userId);
    if (pir == null) {
        pir = new PreferredIntentResolver();
        mPreferredActivities.put(userId, pir);
    }
    return pir;
}
  • 代码2 根据userId获取PreferredIntentResolver 对象,如果没有则创建一个,且放入mPreferredActivities 中。
  • 代码1 判断该Filter是否已经存在,当Fillter不存在,或者当前偏好设置的是 always = true,则将当前偏好加入到PreferredIntentResolver对象中。

注意: Settings 中 mPreferredActivities 这个对象,之后会被用到

launcher应用启动过程

launcher启动过程可以追溯到 ActivtiyManagerServicesystemReady方法。

public ActivityTaskManagerInternal mAtmInternal;

public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
    ...
    //代码1
    t.traceBegin("resumeTopActivities");
    mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
    t.traceEnd();
    ...
}
  • 代码1处 ActivityTaskManagerInternal 的实现类是ActivityTaskManagerService$LocalService ,其调用了ActivityTaskManagerService$LocalService#resumeTopActivities方法

ActivityTaskManagerService$LocalService

@Override
public void resumeTopActivities(boolean scheduleIdle) {
    synchronized (mGlobalLock) {
        mRootWindowContainer.resumeFocusedStacksTopActivities();
        if (scheduleIdle) {
            mStackSupervisor.scheduleIdle();
        }
    }
}

显然调用的是RootWindowContainer.java#resumeFocusedStacksTopActivities

RootWindowContainer.java

//代码1
boolean resumeFocusedStacksTopActivities() {
    return resumeFocusedStacksTopActivities(null, null, null);
}
boolean resumeFocusedStacksTopActivities(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (!mStackSupervisor.readyToResume()) {
        return false;
    }
    boolean result = false;
    if (targetStack != null && (targetStack.isTopStackInDisplayArea()
            || getTopDisplayFocusedStack() == targetStack)) {
        result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        boolean resumedOnDisplay = false;
        final DisplayContent display = getChildAt(displayNdx);
        for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
                final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
                final ActivityRecord topRunningActivity = stack.topRunningActivity();
                if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
                    continue;
                }
                if (stack == targetStack) {
                    // Simply update the result for targetStack because the targetStack had
                    // already resumed in above. We don't want to resume it again, especially in
                    // some cases, it would cause a second launch failure if app process was
                    // dead.
                    resumedOnDisplay |= result;
                    continue;
                }
                if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
                    // Kick off any lingering app transitions form the MoveTaskToFront
                    // operation, but only consider the top task and stack on that display.
                    stack.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
                }
            }
        }
        if (!resumedOnDisplay) {
            final ActivityStack focusedStack = display.getFocusedStack();
            if (focusedStack != null) {
                result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            } else if (targetStack == null) {
                //代码1
                result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                        display.getDefaultTaskDisplayArea());
            }
        }
    }

    return result;
}

boolean resumeHomeActivity(ActivityRecord prev, String reason,
            TaskDisplayArea taskDisplayArea) {
    if (!mService.isBooting() && !mService.isBooted()) {
        // Not ready yet!
        return false;
    }

    if (taskDisplayArea == null) {
        taskDisplayArea = getDefaultTaskDisplayArea();
    }

    final ActivityRecord r = taskDisplayArea.getHomeActivity();
    final String myReason = reason + " resumeHomeActivity";

    // Only resume home activity if isn't finishing.
    //代码3
    if (r != null && !r.finishing) {
        r.moveFocusableActivityToTop(myReason);
        return resumeFocusedStacksTopActivities(r.getRootTask(), prev, null);
    }
    //代码4
    return startHomeOnTaskDisplayArea(mCurrentUser, myReason, taskDisplayArea,
            false /* allowInstrumenting */, false /* fromHomeKey */);
}

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
        boolean allowInstrumenting, boolean fromHomeKey) {
    // Fallback to top focused display area if the provided one is invalid.
    if (taskDisplayArea == null) {
        final ActivityStack stack = getTopDisplayFocusedStack();
        taskDisplayArea = stack != null ? stack.getDisplayArea()
                : getDefaultTaskDisplayArea();
    }

    Intent homeIntent = null;
    ActivityInfo aInfo = null;
    if (taskDisplayArea == getDefaultTaskDisplayArea()) {
        //代码5
        homeIntent = mService.getHomeIntent();
        //代码6
        aInfo = resolveHomeActivity(userId, homeIntent);
    } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
        Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
        aInfo = info.first;
        homeIntent = info.second;
    }
    if (aInfo == null || homeIntent == null) {
        return false;
    }

    if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {
        return false;
    }

    // Updates the home component of the intent.
    homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
    homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
    // Updates the extra information of the intent.
    if (fromHomeKey) {
        homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
        mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "startHomeActivity");
    }
    // Update the reason for ANR debugging to verify if the user activity is the one that
    // actually launched.
    final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
            aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            taskDisplayArea);
    return true;
}

ActivityTaskManagerService.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);
    }
    return intent;
}

  • 代码1 传入的均为null

  • 代码2 显然 targetStack == null,且刚开始,显然此时没有Activity处于 resueme状态,因此resumedOnDisplay的值必定为false,最终走到 resumeHomeActivity 方法。

  • 代码3 此时显然没有homeActivity在,走到代码4

  • 代码4 调用startHomeOnTaskDisplayArea 方法

  • 代码5 调用 ActivityTaskManagerService#getHomeIntent 获取 此时应启动的桌面 信息。在 getHomeIntent方法只不过mTopComponent 值必定为 null,其实不太懂google为何在此处设置这个属性,这个值没有什么意义,因为基本其值基本一直为 null,具体可以看Android 11下ActivityTaskManagerService`。

  • 代码6 调用 resolveHomeActivity 方法。该方法内会读取获取此时应启动的桌面的应用 ComponentName 信息。 ActivityTaskManagerService#resolveHomeActivity

ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
    final int flags = ActivityManagerService.STOCK_PM_FLAGS;
    final ComponentName comp = homeIntent.getComponent();
    ActivityInfo aInfo = null;
    try {
        // 代码1
        if (comp != null) {
            aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
        } else {
            final String resolvedType =
                homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
            //代码2
            final ResolveInfo info = AppGlobals.getPackageManager()
                .resolveIntent(homeIntent, resolvedType, flags, userId);
            if (info != null) {
                aInfo = info.activityInfo;
            }    
        }    
    } catch (RemoteException e) { 
        // ignore
        Slog.i(TAG,"chl resolveHomeActivity 4 aInfo:"+aInfo);
    }    

    if (aInfo == null) {
        Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
        return null;
    }    
    aInfo = new ActivityInfo(aInfo);
    aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
    Thread.dumpStack();
    return aInfo;
}   
  • 代码1 根据上一段代码5中的分析,comp值显然为null,因此走到代码2
  • 代码2 查询符合条件的ActivityInfo。AppGlobals.getPackageManager() 获得的是 PackageManagerService的binder对象。

PackageManagerService.java

@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
        int flags, int privateResolveFlags, int userId, boolean resolveForStart,
        int filterCallingUid) {
    return resolveIntentInternal(
            intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
            filterCallingUid);
}

private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType, int flags,
        @PrivateResolveFlags int privateResolveFlags, int userId, boolean resolveForStart,
        int filterCallingUid) {
    try {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");

        if (!mUserManager.exists(userId)) return null;
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                        flags));
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                flags, privateResolveFlags, filterCallingUid, userId, resolveForStart,
                true /*allowDynamicSplits*/);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

        final boolean queryMayBeFiltered =
                UserHandle.getAppId(filterCallingUid) >= Process.FIRST_APPLICATION_UID
                        && !resolveForStart;
        // 代码1
        final ResolveInfo bestChoice =
                chooseBestActivity(
                        intent, resolvedType, flags, privateResolveFlags, query, userId,
                        queryMayBeFiltered);
        final boolean nonBrowserOnly =
                (privateResolveFlags & PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY) != 0;
        if (nonBrowserOnly && bestChoice != null && bestChoice.handleAllWebDataURI) {
            return null;
        }
        return bestChoice;
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}


  • 代码1 走到此处 chooseBestActivity
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
        int flags, int privateResolveFlags, List<ResolveInfo> query, int userId,
        boolean queryMayBeFiltered) {
    if (query != null) {
        // 有多少符合filter条件的,对于桌面来说,是有多少个桌面Activity。
        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.
            //代码2
            ResolveInfo ri = findPreferredActivityNotLocked(intent, resolvedType,
                    flags, query, r0.priority, true, false, debug, userId, queryMayBeFiltered);
            if (ri != null) {
                return ri;
            }
            //代码3
            ...
        }
    }
    return null;
}
  • 代码2 调用findPreferredActivityNotLocked查找。
// TODO: handle preferred activities missing while user has amnesia
    /** <b>must not hold {@link #mLock}</b> */
    ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags,
            List<ResolveInfo> query, int priority, boolean always,
            boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
        ...
        // writer
        synchronized (mLock) {
            //代码1
            // 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;
            }
            // 代码2
            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...");
            //代码3 
            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), "  ");
                        }
                        //代码4
                        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.
                        //代码5
                        if (always && !pa.mPref.mAlways) {
                            if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry");
                            continue;
                        }
                        // 获取对应 ActivityInfo
                        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");
                            }
                        }
                        final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent)
                                && !isDeviceProvisioned;
                        final boolean allowSetMutation = !excludeSetupWizardHomeActivity
                                && !queryMayBeFiltered;
                        if (ai == null) {
                            // Do not remove launcher's preferred activity during SetupWizard
                            // due to it may not install yet
                            if (!allowSetMutation) {
                                continue;
                            }

                            // 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 && allowSetMutation) {
                                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, and is not a subset of the preferred set, 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, excludeSetupWizardHomeActivity)) {
                                if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) {
                                    if (allowSetMutation) {
                                        // some components of the set are no longer present in
                                        // the query, but the preferred activity can still be reused
                                        if (DEBUG_PREFERRED) {
                                            Slog.i(TAG, "Result set changed, but PreferredActivity"
                                                    + " is still valid as only non-preferred"
                                                    + " components were removed for " + intent
                                                    + " type " + resolvedType);
                                        }
                                        // remove obsolete components and re-add the up-to-date
                                        // filter
                                        PreferredActivity freshPa = new PreferredActivity(pa,
                                                pa.mPref.mMatch,
                                                pa.mPref.discardObsoleteComponents(query),
                                                pa.mPref.mComponent,
                                                pa.mPref.mAlways);
                                        pir.removeFilter(pa);
                                        pir.addFilter(freshPa);
                                        changed = true;
                                    } else {
                                        if (DEBUG_PREFERRED) {
                                            Slog.i(TAG, "Do not remove preferred activity");
                                        }
                                    }
                                } else {
                                    if (allowSetMutation) {
                                        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;
    }
  • 代码1 获取持久作为 activity的偏好,一般此处为null。
  • 代码2 获取setting中的偏好,其在PackageManagerService的代码中调用了 Settings.readLPw方法,该 package-restrictions.xml preferred-activitie 标签下的偏好被读取存入了mPreferredActivities 属性中(如果在使用过程中,用户主动修改了偏好,该 mPreferredActivities 中内容会改变,package-restrictions.xml 文件内容也会改变)
  • 代码3 根据 intent 查询,此处是根据
    <action name="android.intent.action.MAIN" />
    <cat name="android.intent.category.HOME" />
    <cat name="android.intent.category.DEFAULT" />
    
    这三个条件去查找匹配 桌面应用。