Launcher3 如何获取系统上的所有应用程序?

108 阅读1分钟

Launcher3 如何获取系统上的所有应用程序?

通过 LoaderTask

在 Launcher#onCreate 中,运行 LoaderTask。

protected void onCreate(Bundle savedInstanceState) {
    mModel.addCallbacksAndLoad(this)
}

在 LauncherModel#addCallbacksAndLoad 中,使用 HandlerThread launcher-loader 运行 LoaderTask。

fun addCallbacksAndLoad(callbacks: BgDataModel.Callbacks): Boolean {
    synchronized(mLock) {
        addCallbacks(callbacks)
        return startLoader(arrayOf(callbacks))
    }
}

private fun startLoader(newCallbacks: Array<BgDataModel.Callbacks>): Boolean {
    mLoaderTask = LoaderTask(mBgAllAppsList)
    MODEL_EXECUTOR.post(mLoaderTask)
}

在 model.LoaderTask#run 中加载所有应用程序。

public class LoaderTask implements Runnable {
    public void run() {
        Trace.beginSection("LoadAllApps");
        List<LauncherActivityInfo> allActivityList;
        try {
            allActivityList = loadAllApps();
        } finally {
            Trace.endSection();
        }
    }

    private List<LauncherActivityInfo> loadAllApps() {
        final List<UserHandle> profiles = mUserCache.getUserProfiles();
        List<LauncherActivityInfo> allActivityList = new ArrayList<>();
        for (UserHandle user : profiles) {
            final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
            allActivityList.addAll(apps);
        }
        return allActivityList;
    }
}

产生以下两个问题。

问题一:UserHandle 有哪些?

全部来自 UserCache。

UserCache mUserCache = UserCache.INSTANCE.get(mApp.getContext());
final List<UserHandle> profiles = mUserCache.getUserProfiles();

pm.UserCache#getUserProfiles

public List<UserHandle> getUserProfiles() {
    return List.copyOf(mUserToSerialMap.keySet());
}

mUserToSerialMap 里的 Key 来自哪里?

private void updateCache() {
    mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers();
}

util.ApiWrapper#queryAllUsers

public Map<UserHandle, UserIconInfo> queryAllUsers() {
    UserManager um = mContext.getSystemService(UserManager.class);
    Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
    List<UserHandle> usersActual = um.getUserProfiles();
    if (usersActual != null) {
        for (UserHandle user : usersActual) {
            // UserIconInfo info
            users.put(user, info);
        }
    }
    return users;
}

即通过 UserManager 获取 UserHandle。

问题二:mLauncherApps 如何获取?

LauncherApps mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);

Context#getSystemService 即通过跨进程调用。

总结

  • android.os.UserManager#getUserProfiles
  • android.content.pm.LauncherApps#getActivityList(String packageName, UserHandle user)
  • android.content.pm.LauncherActivityInfo