Merge "Fix app pair launches with certain apps" into main
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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)) {
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user