Loading quickstep/src/com/android/quickstep/util/AppPairsController.java +79 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ package com.android.quickstep.util; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_LAUNCH; import static com.android.launcher3.model.data.AppInfo.PACKAGE_KEY_COMPARATOR; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; Loading @@ -30,6 +31,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.isPersisten import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.LauncherApps; import android.util.Log; import android.util.Pair; Loading @@ -42,10 +44,12 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.apppairs.AppPairIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; Loading Loading @@ -93,14 +97,38 @@ public class AppPairsController { } /** * Creates a new app pair ItemInfo and adds it to the workspace * Creates a new app pair ItemInfo and adds it to the workspace. * <br> * We create WorkspaceItemInfos to save onto the app pair in the following way: * <br> 1. We verify that the ComponentKey from our Recents tile corresponds to a real * launchable app in the app store. * <br> 2. If it doesn't, we search for the underlying launchable app via package name, and use * that instead. * <br> 3. If that fails, we re-use the existing WorkspaceItemInfo by cloning it and replacing * its intent with one from PackageManager. * <br> 4. If everything fails, we just use the WorkspaceItemInfo as is, with its existing * intent. This is not preferred, but will still work in most cases (notably it will not work * well on trampoline apps). */ public void saveAppPair(GroupedTaskView gtv) { TaskView.TaskIdAttributeContainer[] attributes = gtv.getTaskIdAttributeContainers(); WorkspaceItemInfo app1 = attributes[0].getItemInfo().clone(); WorkspaceItemInfo app2 = attributes[1].getItemInfo().clone(); app1.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; app2.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; WorkspaceItemInfo recentsInfo1 = attributes[0].getItemInfo(); WorkspaceItemInfo recentsInfo2 = attributes[0].getItemInfo(); WorkspaceItemInfo app1 = lookupLaunchableItem(recentsInfo1.getComponentKey()); WorkspaceItemInfo app2 = lookupLaunchableItem(recentsInfo2.getComponentKey()); // If app lookup fails, use the WorkspaceItemInfo that we have, but try to override default // intent with one from PackageManager. if (app1 == null) { Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo1.title + " failed. Falling back to the WorkspaceItemInfo from Recents."); app1 = convertRecentsItemToAppItem(recentsInfo1); } if (app2 == null) { Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo2.title + " failed. Falling back to the WorkspaceItemInfo from Recents."); app2 = convertRecentsItemToAppItem(recentsInfo2); } @PersistentSnapPosition int snapPosition = gtv.getSnapPosition(); if (!isPersistentSnapPosition(snapPosition)) { Loading Loading @@ -188,6 +216,52 @@ public class AppPairsController { ); } /** * Creates a new launchable WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION by looking the * ComponentKey up in the AllAppsStore. If no app is found, attempts a lookup by package * instead. If that lookup fails, returns null. */ @Nullable private WorkspaceItemInfo lookupLaunchableItem(@Nullable ComponentKey key) { if (key == null) { return null; } AllAppsStore appsStore = Launcher.getLauncher(mContext).getAppsView().getAppsStore(); // Lookup by ComponentKey AppInfo appInfo = appsStore.getApp(key); if (appInfo == null) { // Lookup by package appInfo = appsStore.getApp(key, PACKAGE_KEY_COMPARATOR); } return appInfo != null ? appInfo.makeWorkspaceItem(mContext) : null; } /** * Converts a WorkspaceItemInfo of itemType=ITEM_TYPE_TASK (from a Recents task) to a new * WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION. */ private WorkspaceItemInfo convertRecentsItemToAppItem(WorkspaceItemInfo recentsItem) { if (recentsItem.itemType != LauncherSettings.Favorites.ITEM_TYPE_TASK) { Log.w(TAG, "Expected ItemInfo of type ITEM_TYPE_TASK, but received " + recentsItem.itemType); } WorkspaceItemInfo launchableItem = recentsItem.clone(); PackageManager p = mContext.getPackageManager(); Intent launchIntent = p.getLaunchIntentForPackage(recentsItem.getTargetPackage()); Log.w(TAG, "Initial intent from Recents: " + launchableItem.intent + "\n" + "Intent from PackageManager: " + launchIntent); if (launchIntent != null) { // If lookup from PackageManager fails, just use the existing intent launchableItem.intent = launchIntent; } launchableItem.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; return launchableItem; } /** * Handles the complicated logic for how to animate an app pair entrance when already inside an * app or app pair. Loading src/com/android/launcher3/allapps/AllAppsStore.java +12 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; Loading Loading @@ -138,12 +139,22 @@ public class AllAppsStore<T extends Context & ActivityContext> { /** * Returns {@link AppInfo} if any apps matches with provided {@link ComponentKey}, otherwise * null. * * Uses {@link AppInfo#COMPONENT_KEY_COMPARATOR} as a default comparator. */ @Nullable public AppInfo getApp(ComponentKey key) { return getApp(key, COMPONENT_KEY_COMPARATOR); } /** * Generic version of {@link #getApp(ComponentKey)} that allows comparator to be specified. */ @Nullable public AppInfo getApp(ComponentKey key, Comparator<AppInfo> comparator) { mTempInfo.componentName = key.componentName; mTempInfo.user = key.user; int index = Arrays.binarySearch(mApps, mTempInfo, COMPONENT_KEY_COMPARATOR); int index = Arrays.binarySearch(mApps, mTempInfo, comparator); return index < 0 ? null : mApps[index]; } Loading src/com/android/launcher3/model/data/AppInfo.java +3 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,9 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory { return uc != 0 ? uc : a.componentName.compareTo(b.componentName); }; public static final Comparator<AppInfo> PACKAGE_KEY_COMPARATOR = Comparator.comparingInt( (AppInfo a) -> a.user.hashCode()).thenComparing(ItemInfo::getTargetPackage); /** * The intent used to start the application. */ Loading Loading
quickstep/src/com/android/quickstep/util/AppPairsController.java +79 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ package com.android.quickstep.util; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_LAUNCH; import static com.android.launcher3.model.data.AppInfo.PACKAGE_KEY_COMPARATOR; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; Loading @@ -30,6 +31,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.isPersisten import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.LauncherApps; import android.util.Log; import android.util.Pair; Loading @@ -42,10 +44,12 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.apppairs.AppPairIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; Loading Loading @@ -93,14 +97,38 @@ public class AppPairsController { } /** * Creates a new app pair ItemInfo and adds it to the workspace * Creates a new app pair ItemInfo and adds it to the workspace. * <br> * We create WorkspaceItemInfos to save onto the app pair in the following way: * <br> 1. We verify that the ComponentKey from our Recents tile corresponds to a real * launchable app in the app store. * <br> 2. If it doesn't, we search for the underlying launchable app via package name, and use * that instead. * <br> 3. If that fails, we re-use the existing WorkspaceItemInfo by cloning it and replacing * its intent with one from PackageManager. * <br> 4. If everything fails, we just use the WorkspaceItemInfo as is, with its existing * intent. This is not preferred, but will still work in most cases (notably it will not work * well on trampoline apps). */ public void saveAppPair(GroupedTaskView gtv) { TaskView.TaskIdAttributeContainer[] attributes = gtv.getTaskIdAttributeContainers(); WorkspaceItemInfo app1 = attributes[0].getItemInfo().clone(); WorkspaceItemInfo app2 = attributes[1].getItemInfo().clone(); app1.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; app2.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; WorkspaceItemInfo recentsInfo1 = attributes[0].getItemInfo(); WorkspaceItemInfo recentsInfo2 = attributes[0].getItemInfo(); WorkspaceItemInfo app1 = lookupLaunchableItem(recentsInfo1.getComponentKey()); WorkspaceItemInfo app2 = lookupLaunchableItem(recentsInfo2.getComponentKey()); // If app lookup fails, use the WorkspaceItemInfo that we have, but try to override default // intent with one from PackageManager. if (app1 == null) { Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo1.title + " failed. Falling back to the WorkspaceItemInfo from Recents."); app1 = convertRecentsItemToAppItem(recentsInfo1); } if (app2 == null) { Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo2.title + " failed. Falling back to the WorkspaceItemInfo from Recents."); app2 = convertRecentsItemToAppItem(recentsInfo2); } @PersistentSnapPosition int snapPosition = gtv.getSnapPosition(); if (!isPersistentSnapPosition(snapPosition)) { Loading Loading @@ -188,6 +216,52 @@ public class AppPairsController { ); } /** * Creates a new launchable WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION by looking the * ComponentKey up in the AllAppsStore. If no app is found, attempts a lookup by package * instead. If that lookup fails, returns null. */ @Nullable private WorkspaceItemInfo lookupLaunchableItem(@Nullable ComponentKey key) { if (key == null) { return null; } AllAppsStore appsStore = Launcher.getLauncher(mContext).getAppsView().getAppsStore(); // Lookup by ComponentKey AppInfo appInfo = appsStore.getApp(key); if (appInfo == null) { // Lookup by package appInfo = appsStore.getApp(key, PACKAGE_KEY_COMPARATOR); } return appInfo != null ? appInfo.makeWorkspaceItem(mContext) : null; } /** * Converts a WorkspaceItemInfo of itemType=ITEM_TYPE_TASK (from a Recents task) to a new * WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION. */ private WorkspaceItemInfo convertRecentsItemToAppItem(WorkspaceItemInfo recentsItem) { if (recentsItem.itemType != LauncherSettings.Favorites.ITEM_TYPE_TASK) { Log.w(TAG, "Expected ItemInfo of type ITEM_TYPE_TASK, but received " + recentsItem.itemType); } WorkspaceItemInfo launchableItem = recentsItem.clone(); PackageManager p = mContext.getPackageManager(); Intent launchIntent = p.getLaunchIntentForPackage(recentsItem.getTargetPackage()); Log.w(TAG, "Initial intent from Recents: " + launchableItem.intent + "\n" + "Intent from PackageManager: " + launchIntent); if (launchIntent != null) { // If lookup from PackageManager fails, just use the existing intent launchableItem.intent = launchIntent; } launchableItem.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; return launchableItem; } /** * Handles the complicated logic for how to animate an app pair entrance when already inside an * app or app pair. Loading
src/com/android/launcher3/allapps/AllAppsStore.java +12 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; Loading Loading @@ -138,12 +139,22 @@ public class AllAppsStore<T extends Context & ActivityContext> { /** * Returns {@link AppInfo} if any apps matches with provided {@link ComponentKey}, otherwise * null. * * Uses {@link AppInfo#COMPONENT_KEY_COMPARATOR} as a default comparator. */ @Nullable public AppInfo getApp(ComponentKey key) { return getApp(key, COMPONENT_KEY_COMPARATOR); } /** * Generic version of {@link #getApp(ComponentKey)} that allows comparator to be specified. */ @Nullable public AppInfo getApp(ComponentKey key, Comparator<AppInfo> comparator) { mTempInfo.componentName = key.componentName; mTempInfo.user = key.user; int index = Arrays.binarySearch(mApps, mTempInfo, COMPONENT_KEY_COMPARATOR); int index = Arrays.binarySearch(mApps, mTempInfo, comparator); return index < 0 ? null : mApps[index]; } Loading
src/com/android/launcher3/model/data/AppInfo.java +3 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,9 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory { return uc != 0 ? uc : a.componentName.compareTo(b.componentName); }; public static final Comparator<AppInfo> PACKAGE_KEY_COMPARATOR = Comparator.comparingInt( (AppInfo a) -> a.user.hashCode()).thenComparing(ItemInfo::getTargetPackage); /** * The intent used to start the application. */ Loading