Move multi-instance suppport checking to ApiWrapper

- It's only used for App Pairs & Taskbar (both limited to quickstep
  launcher, and we need to use hidden api to query the multi-instance
  support per-activity.  This is necessary as there can be apps
  installed for a profile, but not the primary user.

Bug: 391611065
Flag: EXEMPT bugfix
Test: atest WMShellUnitTests
Test: Install a multi-instance app only for the non-primary user,
      ensure that we can see the multi-instance UI for these apps

Change-Id: I9d38f32aa38b27b2bffaa744c3f578423f7c7d86
This commit is contained in:
Winson Chung
2025-01-23 00:07:12 +00:00
parent c36a10604c
commit 4443ff10f6
4 changed files with 33 additions and 44 deletions
@@ -144,6 +144,14 @@ open class SystemApiWrapper @Inject constructor(@ApplicationContext context: Con
override fun isNonResizeableActivity(lai: LauncherActivityInfo) =
lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE
override fun supportsMultiInstance(lai: LauncherActivityInfo) : Boolean {
return try {
super.supportsMultiInstance(lai) || lai.supportsMultiInstance()
} catch (e: Exception) {
false
}
}
/**
* Starts an Activity which can be used to set this Launcher as the HOME app, via a consent
* screen. In case the consent screen cannot be shown, or the user does not set current Launcher
@@ -215,8 +215,7 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
PackageManagerHelper.getLoadingProgress(lai),
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
info.setNonResizeable(apiWrapper.isNonResizeableActivity(lai));
info.setSupportsMultiInstance(
pmHelper.supportsMultiInstance(lai.getComponentName()));
info.setSupportsMultiInstance(apiWrapper.supportsMultiInstance(lai));
return (oldProgressLevel != info.getProgressLevel())
|| (oldRuntimeStatusFlags != info.runtimeStatusFlags);
}
+24 -2
View File
@@ -59,10 +59,13 @@ public class ApiWrapper {
LauncherAppComponent::getApiWrapper);
protected final Context mContext;
private final String[] mLegacyMultiInstanceSupportedApps;
@Inject
public ApiWrapper(@ApplicationContext Context context) {
mContext = context;
mLegacyMultiInstanceSupportedApps = context.getResources().getStringArray(
com.android.launcher3.R.array.config_appsSupportMultiInstancesSplit);
}
/**
@@ -157,11 +160,30 @@ public class ApiWrapper {
/**
* Checks if an activity is flagged as non-resizeable.
*/
public boolean isNonResizeableActivity(LauncherActivityInfo lai) {
// Overridden in quickstep
public boolean isNonResizeableActivity(@NonNull LauncherActivityInfo lai) {
// Overridden in Quickstep
return false;
}
/**
* Checks if an activity supports multi-instance.
*/
public boolean supportsMultiInstance(@NonNull LauncherActivityInfo lai) {
// Check app multi-instance properties after V
if (!Utilities.ATLEAST_V) {
return false;
}
// Check the legacy hardcoded allowlist first
for (String pkg : mLegacyMultiInstanceSupportedApps) {
if (pkg.equals(lai.getComponentName().getPackageName())) {
return true;
}
}
// Overridden in Quickstep
return false;
}
/**
* Starts an Activity which can be used to set this Launcher as the HOME app, via a consent
* screen. In case the consent screen cannot be shown, or the user does not set current Launcher
@@ -16,8 +16,6 @@
package com.android.launcher3.util;
import static android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
import android.content.ActivityNotFoundException;
@@ -41,7 +39,6 @@ import androidx.annotation.Nullable;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dagger.ApplicationContext;
import com.android.launcher3.dagger.LauncherAppSingleton;
import com.android.launcher3.dagger.LauncherBaseAppComponent;
@@ -77,15 +74,11 @@ public class PackageManagerHelper {
@NonNull
private final LauncherApps mLauncherApps;
private final String[] mLegacyMultiInstanceSupportedApps;
@Inject
public PackageManagerHelper(@ApplicationContext final Context context) {
mContext = context;
mPm = context.getPackageManager();
mLauncherApps = Objects.requireNonNull(context.getSystemService(LauncherApps.class));
mLegacyMultiInstanceSupportedApps = mContext.getResources().getStringArray(
R.array.config_appsSupportMultiInstancesSplit);
}
/**
@@ -192,39 +185,6 @@ public class PackageManagerHelper {
return (int) (100 * info.getLoadingProgress());
}
/**
* Returns whether the given component or its application has the multi-instance property set.
*/
public boolean supportsMultiInstance(@NonNull ComponentName component) {
// Check the legacy hardcoded allowlist first
for (String pkg : mLegacyMultiInstanceSupportedApps) {
if (pkg.equals(component.getPackageName())) {
return true;
}
}
// Check app multi-instance properties after V
if (!Utilities.ATLEAST_V) {
return false;
}
try {
// Check if the component has the multi-instance property
return mPm.getProperty(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, component)
.getBoolean();
} catch (PackageManager.NameNotFoundException e1) {
try {
// Check if the application has the multi-instance property
return mPm.getProperty(PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI,
component.getPackageName())
.getBoolean();
} catch (PackageManager.NameNotFoundException e2) {
// Fall through
}
}
return false;
}
/**
* Returns whether two apps should be considered the same for multi-instance purposes, which
* requires additional checks to ensure they can be started as multiple instances.