diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index 31d40710bc..c4ee11a8d1 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -38,6 +38,7 @@ + com.android.launcher3.uioverrides.SystemApiWrapper diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 390dec9a66..98ce2edae4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -113,8 +113,8 @@ import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy; -import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.ActivityOptionsWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.Executors; @@ -1120,7 +1120,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } else if (info.isPromise()) { TestLogging.recordEvent( TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon"); - intent = ApiWrapper.getAppMarketActivityIntent(this, + intent = ApiWrapper.INSTANCE.get(this).getAppMarketActivityIntent( info.getTargetPackage(), Process.myUserHandle()); startActivity(intent); diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java deleted file mode 100644 index 873dea80e3..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.uioverrides; - -import android.app.ActivityOptions; -import android.app.PendingIntent; -import android.app.Person; -import android.content.Context; -import android.content.Intent; -import android.content.IntentSender; -import android.content.pm.ActivityInfo; -import android.content.pm.LauncherActivityInfo; -import android.content.pm.LauncherApps; -import android.content.pm.LauncherUserInfo; -import android.content.pm.ShortcutInfo; -import android.graphics.drawable.ColorDrawable; -import android.net.Uri; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.ArrayMap; -import android.window.RemoteTransition; - -import com.android.launcher3.Flags; -import com.android.launcher3.Utilities; -import com.android.launcher3.proxy.ProxyActivityStarter; -import com.android.launcher3.util.StartActivityParams; -import com.android.launcher3.util.UserIconInfo; -import com.android.quickstep.util.FadeOutRemoteTransition; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * A wrapper for the hidden API calls - */ -public class ApiWrapper { - - public static final boolean TASKBAR_DRAWN_IN_PROCESS = true; - - public static Person[] getPersons(ShortcutInfo si) { - Person[] persons = si.getPersons(); - return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons; - } - - public static Map getActivityOverrides(Context context) { - return context.getSystemService(LauncherApps.class).getActivityOverrides(); - } - - /** - * Creates an ActivityOptions to play fade-out animation on closing targets - */ - public static ActivityOptions createFadeOutAnimOptions(Context context) { - ActivityOptions options = ActivityOptions.makeBasic(); - options.setRemoteTransition(new RemoteTransition(new FadeOutRemoteTransition())); - return options; - } - - /** - * Returns a map of all users on the device to their corresponding UI properties - */ - public static Map queryAllUsers(Context context) { - UserManager um = context.getSystemService(UserManager.class); - Map users = new ArrayMap<>(); - List usersActual = um.getUserProfiles(); - if (usersActual != null) { - for (UserHandle user : usersActual) { - if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - LauncherUserInfo launcherUserInfo = launcherApps.getLauncherUserInfo(user); - if (launcherUserInfo == null) { - continue; - } - // UserTypes not supported in Launcher are deemed to be the current - // Foreground User. - int userType = switch (launcherUserInfo.getUserType()) { - case UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK; - case UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED; - case UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE; - default -> UserIconInfo.TYPE_MAIN; - }; - long serial = launcherUserInfo.getUserSerialNumber(); - users.put(user, new UserIconInfo(user, userType, serial)); - } else { - long serial = um.getSerialNumberForUser(user); - - // Simple check to check if the provided user is work profile - // TODO: Migrate to a better platform API - NoopDrawable d = new NoopDrawable(); - boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user)); - UserIconInfo info = new UserIconInfo( - user, - isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, - serial); - users.put(user, info); - } - } - } - return users; - } - - /** - * Returns the list of the system packages that are installed at user creation. - * An empty list denotes that all system packages are installed for that user at creation. - */ - public static List getPreInstalledSystemPackages(Context context, UserHandle user) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace() - && Flags.privateSpaceSysAppsSeparation()) { - return launcherApps.getPreInstalledSystemPackages(user); - } else { - return new ArrayList<>(); - } - } - - /** - * Returns an intent which can be used to start the App Market activity (Installer - * Activity). - */ - public static Intent getAppMarketActivityIntent(Context context, String packageName, - UserHandle user) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - if (android.os.Flags.allowPrivateProfile() - && Flags.enablePrivateSpace() - && (Flags.privateSpaceAppInstallerButton() - || Flags.enablePrivateSpaceInstallShortcut())) { - StartActivityParams params = new StartActivityParams((PendingIntent) null, 0); - params.intentSender = launcherApps.getAppMarketActivityIntent(packageName, user); - ActivityOptions options = ActivityOptions.makeBasic() - .setPendingIntentBackgroundActivityStartMode(ActivityOptions - .MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - params.options = options.toBundle(); - params.requireActivityResult = false; - return ProxyActivityStarter.getLaunchIntent(context, params); - } else { - return new Intent(Intent.ACTION_VIEW) - .setData(new Uri.Builder() - .scheme("market") - .authority("details") - .appendQueryParameter("id", packageName) - .build()) - .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app") - .authority(context.getPackageName()).build()); - } - } - - /** - * Returns an intent which can be used to open Private Space Settings. - */ - public static Intent getPrivateSpaceSettingsIntent(Context context) { - if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) { - LauncherApps launcherApps = context.getSystemService(LauncherApps.class); - IntentSender intentSender = launcherApps.getPrivateSpaceSettingsIntent(); - if (intentSender == null) { - return null; - } - StartActivityParams params = new StartActivityParams((PendingIntent) null, 0); - params.intentSender = intentSender; - ActivityOptions options = ActivityOptions.makeBasic() - .setPendingIntentBackgroundActivityStartMode(ActivityOptions - .MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - params.options = options.toBundle(); - params.requireActivityResult = false; - return ProxyActivityStarter.getLaunchIntent(context, params); - } - return null; - } - - /** - * Checks if an activity is flagged as non-resizeable. - */ - public static boolean isNonResizeableActivity(LauncherActivityInfo lai) { - return lai.getActivityInfo().resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE; - } - - private static class NoopDrawable extends ColorDrawable { - @Override - public int getIntrinsicHeight() { - return 1; - } - - @Override - public int getIntrinsicWidth() { - return 1; - } - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt new file mode 100644 index 0000000000..535b4c2986 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.uioverrides + +import android.app.ActivityOptions +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.pm.ActivityInfo +import android.content.pm.LauncherActivityInfo +import android.content.pm.LauncherApps +import android.content.pm.ShortcutInfo +import android.os.Flags.allowPrivateProfile +import android.os.UserHandle +import android.os.UserManager +import android.util.ArrayMap +import android.window.RemoteTransition +import com.android.launcher3.Flags.enablePrivateSpace +import com.android.launcher3.Flags.enablePrivateSpaceInstallShortcut +import com.android.launcher3.Flags.privateSpaceAppInstallerButton +import com.android.launcher3.Flags.privateSpaceSysAppsSeparation +import com.android.launcher3.Utilities +import com.android.launcher3.proxy.ProxyActivityStarter +import com.android.launcher3.util.ApiWrapper +import com.android.launcher3.util.StartActivityParams +import com.android.launcher3.util.UserIconInfo +import com.android.quickstep.util.FadeOutRemoteTransition + +/** A wrapper for the hidden API calls */ +class SystemApiWrapper(context: Context?) : ApiWrapper(context) { + + override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY + + override fun getActivityOverrides(): Map = + mContext.getSystemService(LauncherApps::class.java)!!.activityOverrides + + override fun createFadeOutAnimOptions(): ActivityOptions = + ActivityOptions.makeBasic().apply { + remoteTransition = RemoteTransition(FadeOutRemoteTransition()) + } + + override fun queryAllUsers(): Map { + if (!allowPrivateProfile() || !enablePrivateSpace()) { + return super.queryAllUsers() + } + val users = ArrayMap() + mContext.getSystemService(UserManager::class.java)!!.userProfiles?.forEach { user -> + mContext.getSystemService(LauncherApps::class.java)!!.getLauncherUserInfo(user)?.apply { + users[user] = + UserIconInfo( + user, + when (userType) { + UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK + UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED + UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE + else -> UserIconInfo.TYPE_MAIN + }, + userSerialNumber.toLong() + ) + } + } + return users + } + + override fun getPreInstalledSystemPackages(user: UserHandle): List = + if (allowPrivateProfile() && enablePrivateSpace() && privateSpaceSysAppsSeparation()) + mContext + .getSystemService(LauncherApps::class.java)!! + .getPreInstalledSystemPackages(user) + else ArrayList() + + override fun getAppMarketActivityIntent(packageName: String, user: UserHandle): Intent = + if ( + allowPrivateProfile() && + enablePrivateSpace() && + (privateSpaceAppInstallerButton() || enablePrivateSpaceInstallShortcut()) + ) + ProxyActivityStarter.getLaunchIntent( + mContext, + StartActivityParams(null as PendingIntent?, 0).apply { + intentSender = + mContext + .getSystemService(LauncherApps::class.java)!! + .getAppMarketActivityIntent(packageName, user) + options = + ActivityOptions.makeBasic() + .setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + ) + .toBundle() + requireActivityResult = false + } + ) + else super.getAppMarketActivityIntent(packageName, user) + + /** Returns an intent which can be used to open Private Space Settings. */ + override fun getPrivateSpaceSettingsIntent(): Intent? = + if (allowPrivateProfile() && enablePrivateSpace()) + ProxyActivityStarter.getLaunchIntent( + mContext, + StartActivityParams(null as PendingIntent?, 0).apply { + intentSender = + mContext + .getSystemService(LauncherApps::class.java) + ?.privateSpaceSettingsIntent + ?: return null + options = + ActivityOptions.makeBasic() + .setPendingIntentBackgroundActivityStartMode( + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED + ) + .toBundle() + requireActivityResult = false + } + ) + else null + + override fun isNonResizeableActivity(lai: LauncherActivityInfo) = + lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE +} diff --git a/res/values/config.xml b/res/values/config.xml index 599584b64b..f820e763fb 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -78,6 +78,7 @@ + diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java index c7cdfa8c69..cf865288c4 100644 --- a/src/com/android/launcher3/AutoInstallsLayout.java +++ b/src/com/android/launcher3/AutoInstallsLayout.java @@ -52,7 +52,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.shortcuts.ShortcutKey; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.Partner; import com.android.launcher3.util.Thunk; @@ -203,7 +203,7 @@ public class AutoInstallsLayout { mIdp = LauncherAppState.getIDP(context); mRowCount = mIdp.numRows; mColumnCount = mIdp.numColumns; - mActivityOverride = ApiWrapper.getActivityOverrides(context); + mActivityOverride = ApiWrapper.INSTANCE.get(context).getActivityOverrides(); } /** diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 3ddc7aa5e7..6cb33a8c29 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -63,13 +63,13 @@ import com.android.launcher3.responsive.ResponsiveCellSpecsProvider; import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType; import com.android.launcher3.responsive.ResponsiveSpec.DimensionType; import com.android.launcher3.responsive.ResponsiveSpecsProvider; -import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.CellContentDimensions; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.IconSizeSteps; import com.android.launcher3.util.ResourceHelper; import com.android.launcher3.util.WindowBounds; +import com.android.launcher3.util.window.WindowManagerProxy; import java.io.PrintWriter; import java.util.Locale; @@ -350,7 +350,8 @@ public class DeviceProfile { isTablet = info.isTablet(windowBounds); isPhone = !isTablet; isTwoPanels = isTablet && isMultiDisplay; - isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS; + isTaskbarPresent = isTablet + && WindowManagerProxy.INSTANCE.get(context).isTaskbarDrawnInProcess(); // Some more constants. context = getContext(context, info, isVerticalBarLayout() || (isTablet && isLandscape) diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index be120cce75..1def8a33ac 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -72,7 +72,7 @@ import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.PrivateSpaceInstallAppButtonInfo; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.SettingsCache; import com.android.launcher3.views.ActivityContext; @@ -122,7 +122,9 @@ public class PrivateProfileManager extends UserProfileManager { super(userManager, statsLogManager, userCache); mAllApps = allApps; mPrivateProfileMatcher = (user) -> userCache.getUserInfo(user).isPrivate(); - UI_HELPER_EXECUTOR.post(this::initializeInBackgroundThread); + + Context appContext = allApps.getContext().getApplicationContext(); + UI_HELPER_EXECUTOR.post(() -> initializeInBackgroundThread(appContext)); mPsHeaderHeight = mAllApps.getContext().getResources().getDimensionPixelSize( R.dimen.ps_header_height); } @@ -187,7 +189,7 @@ public class PrivateProfileManager extends UserProfileManager { /** Whether private profile should be hidden on Launcher. */ public boolean isPrivateSpaceHidden() { return getCurrentState() == STATE_DISABLED && SettingsCache.INSTANCE - .get(mAllApps.mActivityContext).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0); + .get(mAllApps.getContext()).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0); } /** @@ -215,8 +217,8 @@ public class PrivateProfileManager extends UserProfileManager { /** Opens the Private Space Settings Page. */ public void openPrivateSpaceSettings() { if (mPrivateSpaceSettingsAvailable) { - mAllApps.getContext() - .startActivity(ApiWrapper.getPrivateSpaceSettingsIntent(mAllApps.getContext())); + mAllApps.getContext().startActivity( + ApiWrapper.INSTANCE.get(mAllApps.getContext()).getPrivateSpaceSettingsIntent()); } } @@ -239,33 +241,17 @@ public class PrivateProfileManager extends UserProfileManager { * This case should still be ok, as locking the Private Space container and unlocking it, * reloads the values, fixing the incorrect UI. */ - private void initializeInBackgroundThread() { + private void initializeInBackgroundThread(Context appContext) { Preconditions.assertNonUiThread(); - setPreInstalledSystemPackages(); - setAppInstallerIntent(); - initializePrivateSpaceSettingsState(); - } - - private void initializePrivateSpaceSettingsState() { - Preconditions.assertNonUiThread(); - Intent psSettingsIntent = ApiWrapper.getPrivateSpaceSettingsIntent(mAllApps.getContext()); - setPrivateSpaceSettingsAvailable(psSettingsIntent != null); - } - - private void setPreInstalledSystemPackages() { - Preconditions.assertNonUiThread(); - if (getProfileUser() != null) { - mPreInstalledSystemPackages = new HashSet<>(ApiWrapper - .getPreInstalledSystemPackages(mAllApps.getContext(), getProfileUser())); - } - } - - private void setAppInstallerIntent() { - Preconditions.assertNonUiThread(); - if (getProfileUser() != null) { - mAppInstallerIntent = ApiWrapper.getAppMarketActivityIntent(mAllApps.getContext(), - BuildConfig.APPLICATION_ID, getProfileUser()); + ApiWrapper apiWrapper = ApiWrapper.INSTANCE.get(appContext); + UserHandle profileUser = getProfileUser(); + if (profileUser != null) { + mPreInstalledSystemPackages = new HashSet<>( + apiWrapper.getPreInstalledSystemPackages(profileUser)); + mAppInstallerIntent = apiWrapper + .getAppMarketActivityIntent(BuildConfig.APPLICATION_ID, profileUser); } + setPrivateSpaceSettingsAvailable(apiWrapper.getPrivateSpaceSettingsIntent() != null); } @VisibleForTesting diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java index 29aa216a3b..05fdcef461 100644 --- a/src/com/android/launcher3/dragndrop/AddItemActivity.java +++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java @@ -67,7 +67,7 @@ import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.pm.PinRequestHelper; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.views.AbstractSlideInView; @@ -259,7 +259,8 @@ public class AddItemActivity extends BaseActivity .setPackage(getPackageName()) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Launcher.ACTIVITY_TRACKER.registerCallback(listener, "AddItemActivity.onLongClick"); - startActivity(homeIntent, ApiWrapper.createFadeOutAnimOptions(this).toBundle()); + startActivity(homeIntent, + ApiWrapper.INSTANCE.get(this).createFadeOutAnimOptions().toBundle()); logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED); mFinishOnPause = true; return false; diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index ea1ae2ed24..e42e67924b 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -48,7 +48,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.PackageInstallInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutRequest; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; @@ -286,7 +286,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) { if (activities != null && !activities.isEmpty()) { - si.status = ApiWrapper + si.status = ApiWrapper.INSTANCE.get(context) .isNonResizeableActivity(activities.get(0)) ? si.status | WorkspaceItemInfo.FLAG_NON_RESIZEABLE : si.status & ~WorkspaceItemInfo.FLAG_NON_RESIZEABLE; diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index a900d1fa55..ff95bbbb73 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -41,7 +41,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.pm.PackageInstallInfo import com.android.launcher3.shortcuts.ShortcutKey -import com.android.launcher3.uioverrides.ApiWrapper +import com.android.launcher3.util.ApiWrapper import com.android.launcher3.util.ComponentKey import com.android.launcher3.util.PackageManagerHelper import com.android.launcher3.util.PackageUserKey @@ -325,7 +325,7 @@ class WorkspaceItemProcessor( } val activityInfo = c.launcherActivityInfo if (activityInfo != null) { - if (ApiWrapper.isNonResizeableActivity(activityInfo)) { + if (ApiWrapper.INSTANCE.get(app.context).isNonResizeableActivity(activityInfo)) { info.status = info.status or WorkspaceItemInfo.FLAG_NON_RESIZEABLE } info.setProgressLevel( diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java index be3aa101ac..faeed29c78 100644 --- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java +++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java @@ -28,7 +28,7 @@ import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags; import com.android.launcher3.icons.FastBitmapDrawable; import com.android.launcher3.logging.FileLog; import com.android.launcher3.pm.PackageInstallInfo; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; /** * Represents an ItemInfo which also holds an icon. @@ -251,8 +251,8 @@ public abstract class ItemInfoWithIcon extends ItemInfo { String targetPackage = getTargetPackage(); return targetPackage != null - ? ApiWrapper.getAppMarketActivityIntent( - context, targetPackage, Process.myUserHandle()) + ? ApiWrapper.INSTANCE.get(context).getAppMarketActivityIntent( + targetPackage, Process.myUserHandle()) : null; } diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java index 9917ad7a64..5ae70039ab 100644 --- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java +++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java @@ -32,7 +32,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.icons.IconCache; import com.android.launcher3.pm.UserCache; import com.android.launcher3.shortcuts.ShortcutKey; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ContentWriter; import java.util.Arrays; @@ -201,7 +201,7 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon { runtimeStatusFlags &= ~FLAG_DISABLED_VERSION_LOWER; } - Person[] persons = ApiWrapper.getPersons(shortcutInfo); + Person[] persons = ApiWrapper.INSTANCE.get(context).getPersons(shortcutInfo); personKeys = persons.length == 0 ? Utilities.EMPTY_STRING_ARRAY : Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new); } diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java index 032de31ed7..185e0b55bd 100644 --- a/src/com/android/launcher3/pm/UserCache.java +++ b/src/com/android/launcher3/pm/UserCache.java @@ -17,7 +17,6 @@ package com.android.launcher3.pm; import static com.android.launcher3.Utilities.ATLEAST_U; -import static com.android.launcher3.uioverrides.ApiWrapper.queryAllUsers; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.content.Context; @@ -34,6 +33,7 @@ import androidx.annotation.WorkerThread; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.UserBadgeDrawable; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SafeCloseable; @@ -119,7 +119,7 @@ public class UserCache implements SafeCloseable { @WorkerThread private void updateCache() { - mUserToSerialMap = queryAllUsers(mContext); + mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers(); } /** diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 0af7e677ed..0c5a0ec171 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -31,7 +31,7 @@ import com.android.launcher3.model.WidgetItem; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.PackageManagerHelper; @@ -259,10 +259,8 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { Intent intent = - ApiWrapper.getAppMarketActivityIntent( - view.getContext(), - mItemInfo.getTargetComponent().getPackageName(), - mSpaceUser); + ApiWrapper.INSTANCE.get(view.getContext()).getAppMarketActivityIntent( + mItemInfo.getTargetComponent().getPackageName(), mSpaceUser); mTarget.startActivitySafely(view, intent, mItemInfo); AbstractFloatingView.closeAllOpenViews(mTarget); mTarget.getStatsLogManager() @@ -303,9 +301,8 @@ public abstract class SystemShortcut extends ItemInfo @Override public void onClick(View view) { - Intent intent = ApiWrapper.getAppMarketActivityIntent(view.getContext(), - mItemInfo.getTargetComponent().getPackageName(), - Process.myUserHandle()); + Intent intent = ApiWrapper.INSTANCE.get(view.getContext()).getAppMarketActivityIntent( + mItemInfo.getTargetComponent().getPackageName(), Process.myUserHandle()); mTarget.startActivitySafely(view, intent, mItemInfo); AbstractFloatingView.closeAllOpenViews(mTarget); } diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index b4e6365d66..d702e51881 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -70,7 +70,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.LogConfig; @@ -560,9 +560,8 @@ public class RestoreDbTask { protected static void maybeOverrideShortcuts(Context context, ModelDbController controller, SQLiteDatabase db, long currentUser) { - Map activityOverrides = ApiWrapper.getActivityOverrides( - context); - + Map activityOverrides = + ApiWrapper.INSTANCE.get(context).getActivityOverrides(); if (activityOverrides == null || activityOverrides.isEmpty()) { return; } diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 50df7757ec..49ec0cb3f4 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -63,7 +63,7 @@ import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; -import com.android.launcher3.uioverrides.ApiWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.views.FloatingIconView; import com.android.launcher3.views.Snackbar; @@ -234,7 +234,7 @@ public class ItemClickHandler { } } // Fallback to using custom market intent. - Intent intent = ApiWrapper.getAppMarketActivityIntent(launcher, + Intent intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent( packageName, Process.myUserHandle()); launcher.startActivitySafely(v, intent, item); }; @@ -372,12 +372,12 @@ public class ItemClickHandler { if (item instanceof ItemInfoWithIcon itemInfoWithIcon) { if ((itemInfoWithIcon.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) { - intent = ApiWrapper.getAppMarketActivityIntent(launcher, + intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent( itemInfoWithIcon.getTargetComponent().getPackageName(), Process.myUserHandle()); } else if (itemInfoWithIcon.itemType == LauncherSettings.Favorites.ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON) { - intent = ApiWrapper.getAppMarketActivityIntent(launcher, + intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent( BuildConfig.APPLICATION_ID, launcher.getAppsView().getPrivateProfileManager().getProfileUser()); launcher.getStatsLogManager().logger().log( diff --git a/src_no_quickstep/com/android/launcher3/uioverrides/ApiWrapper.java b/src/com/android/launcher3/util/ApiWrapper.java similarity index 68% rename from src_no_quickstep/com/android/launcher3/uioverrides/ApiWrapper.java rename to src/com/android/launcher3/util/ApiWrapper.java index 90271c1cae..6429a437bf 100644 --- a/src_no_quickstep/com/android/launcher3/uioverrides/ApiWrapper.java +++ b/src/com/android/launcher3/util/ApiWrapper.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package com.android.launcher3.uioverrides; +package com.android.launcher3.util; + +import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; import android.app.ActivityOptions; import android.app.Person; @@ -28,10 +30,12 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; -import com.android.launcher3.Utilities; -import com.android.launcher3.util.UserIconInfo; +import androidx.annotation.Nullable; + +import com.android.launcher3.BuildConfig; +import com.android.launcher3.R; +import com.android.launcher3.Utilities; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -39,30 +43,40 @@ import java.util.Map; /** * A wrapper for the hidden API calls */ -public class ApiWrapper { +public class ApiWrapper implements ResourceBasedOverride, SafeCloseable { - public static final boolean TASKBAR_DRAWN_IN_PROCESS = false; + public static final MainThreadInitializedObject INSTANCE = + forOverride(ApiWrapper.class, R.string.api_wrapper_class); - public static Person[] getPersons(ShortcutInfo si) { + protected final Context mContext; + + public ApiWrapper(Context context) { + mContext = context; + } + + /** + * Returns the list of persons associated with the provided shortcut info + */ + public Person[] getPersons(ShortcutInfo si) { return Utilities.EMPTY_PERSON_ARRAY; } - public static Map getActivityOverrides(Context context) { + public Map getActivityOverrides() { return Collections.emptyMap(); } /** * Creates an ActivityOptions to play fade-out animation on closing targets */ - public static ActivityOptions createFadeOutAnimOptions(Context context) { - return ActivityOptions.makeCustomAnimation(context, 0, android.R.anim.fade_out); + public ActivityOptions createFadeOutAnimOptions() { + return ActivityOptions.makeCustomAnimation(mContext, 0, android.R.anim.fade_out); } /** * Returns a map of all users on the device to their corresponding UI properties */ - public static Map queryAllUsers(Context context) { - UserManager um = context.getSystemService(UserManager.class); + public Map queryAllUsers() { + UserManager um = mContext.getSystemService(UserManager.class); Map users = new ArrayMap<>(); List usersActual = um.getUserProfiles(); if (usersActual != null) { @@ -72,7 +86,7 @@ public class ApiWrapper { // Simple check to check if the provided user is work profile // TODO: Migrate to a better platform API NoopDrawable d = new NoopDrawable(); - boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user)); + boolean isWork = (d != mContext.getPackageManager().getUserBadgedIcon(d, user)); UserIconInfo info = new UserIconInfo( user, isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, @@ -87,16 +101,15 @@ public class ApiWrapper { * Returns the list of the system packages that are installed at user creation. * An empty list denotes that all system packages are installed for that user at creation. */ - public static List getPreInstalledSystemPackages(Context context, UserHandle user) { - return new ArrayList<>(); + public List getPreInstalledSystemPackages(UserHandle user) { + return Collections.emptyList(); } /** * Returns an intent which can be used to start the App Market activity (Installer * Activity). */ - public static Intent getAppMarketActivityIntent(Context context, String packageName, - UserHandle user) { + public Intent getAppMarketActivityIntent(String packageName, UserHandle user) { return new Intent(Intent.ACTION_VIEW) .setData(new Uri.Builder() .scheme("market") @@ -104,24 +117,27 @@ public class ApiWrapper { .appendQueryParameter("id", packageName) .build()) .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app") - .authority(context.getPackageName()).build()); + .authority(BuildConfig.APPLICATION_ID).build()); } /** * Returns an intent which can be used to open Private Space Settings. */ - public static Intent getPrivateSpaceSettingsIntent(Context context) { + @Nullable + public Intent getPrivateSpaceSettingsIntent() { return null; } /** * Checks if an activity is flagged as non-resizeable. */ - public static boolean isNonResizeableActivity(LauncherActivityInfo lai) { + public boolean isNonResizeableActivity(LauncherActivityInfo lai) { // Overridden in quickstep return false; } + @Override + public void close() { } private static class NoopDrawable extends ColorDrawable { @Override diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 316506ab4a..6ed875de91 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -16,6 +16,8 @@ package com.android.launcher3.util; +import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE; + import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; @@ -46,7 +48,6 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.uioverrides.ApiWrapper; import java.util.List; import java.util.Objects; @@ -169,11 +170,9 @@ public class PackageManagerHelper { * Starts the details activity for {@code info} */ public void startDetailsActivityForInfo(ItemInfo info, Rect sourceBounds, Bundle opts) { - if (info instanceof ItemInfoWithIcon - && (((ItemInfoWithIcon) info).runtimeStatusFlags - & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) { - ItemInfoWithIcon appInfo = (ItemInfoWithIcon) info; - mContext.startActivity(ApiWrapper.getAppMarketActivityIntent(mContext, + if (info instanceof ItemInfoWithIcon appInfo + && (appInfo.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) { + mContext.startActivity(ApiWrapper.INSTANCE.get(mContext).getAppMarketActivityIntent( appInfo.getTargetComponent().getPackageName(), Process.myUserHandle())); return; } diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index 4a906d33e1..998191e7fc 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -93,6 +93,13 @@ public class WindowManagerProxy implements ResourceBasedOverride { mTaskbarDrawnInProcess = taskbarDrawnInProcess; } + /** + * Returns true if taskbar is drawn in process + */ + public boolean isTaskbarDrawnInProcess() { + return mTaskbarDrawnInProcess; + } + /** * Returns a map of normalized info of internal displays to estimated window bounds * for that display diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index ffcf83f303..577334bec3 100644 --- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -38,17 +38,18 @@ import com.android.launcher3.util.rule.setFlags import com.android.launcher3.util.window.CachedDisplayInfo import com.android.launcher3.util.window.WindowManagerProxy import com.google.common.truth.Truth -import org.junit.Rule -import org.mockito.kotlin.any -import org.mockito.kotlin.mock -import org.mockito.kotlin.spy -import org.mockito.kotlin.whenever import java.io.BufferedReader import java.io.File import java.io.PrintWriter import java.io.StringWriter import kotlin.math.max import kotlin.math.min +import org.junit.Rule +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.whenever /** * This is an abstract class for DeviceProfile tests that create an InvariantDeviceProfile based on @@ -286,6 +287,9 @@ abstract class AbstractDeviceProfileTest { .thenReturn( if (isGestureMode) NavigationMode.NO_BUTTON else NavigationMode.THREE_BUTTONS ) + doReturn(WindowManagerProxy.INSTANCE[runningContext].isTaskbarDrawnInProcess) + .whenever(windowManagerProxy) + .isTaskbarDrawnInProcess() val density = densityDpi / DisplayMetrics.DENSITY_DEFAULT.toFloat() val config = diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java index e9d2f6e61a..8f398a66ff 100644 --- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java +++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java @@ -47,8 +47,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.pm.UserCache; -import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.ActivityContextWrapper; +import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.UserIconInfo; import com.android.launcher3.util.rule.TestStabilityRule; @@ -108,7 +108,8 @@ public class PrivateProfileManagerTest { when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO); when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO); when(mAllApps.getContext()).thenReturn(mContext); - when(mAllApps.getContext().getResources()).thenReturn(mResources); + when(mContext.getResources()).thenReturn(mResources); + when(mContext.getApplicationContext()).thenReturn(getApplicationContext()); when(mAllApps.getAppsStore()).thenReturn(mAllAppsStore); when(mAllApps.getActiveRecyclerView()).thenReturn(mAllAppsRecyclerView); when(mContext.getPackageManager()).thenReturn(mPackageManager); @@ -200,14 +201,15 @@ public class PrivateProfileManagerTest { @Test public void openPrivateSpaceSettings_triggersCorrectIntent() { - Intent expectedIntent = ApiWrapper.getPrivateSpaceSettingsIntent(mContext); + Intent expectedIntent = ApiWrapper.INSTANCE.get(mContext).getPrivateSpaceSettingsIntent(); ArgumentCaptor acIntent = ArgumentCaptor.forClass(Intent.class); mPrivateProfileManager.setPrivateSpaceSettingsAvailable(true); mPrivateProfileManager.openPrivateSpaceSettings(); Mockito.verify(mContext).startActivity(acIntent.capture()); - assertEquals("Intent Action is different", expectedIntent, acIntent.getValue()); + assertEquals("Intent Action is different", + expectedIntent.toUri(0), acIntent.getValue().toUri(0)); } private static void awaitTasksCompleted() throws Exception {