diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig index 949acc1f45..ee7e975de1 100644 --- a/aconfig/launcher.aconfig +++ b/aconfig/launcher.aconfig @@ -310,6 +310,13 @@ flag { bug: "346408388" } +flag { + name: "all_apps_sheet_for_handheld" + namespace: "launcher" + description: "All Apps will be presented on a bottom sheet in handheld mode" + bug: "374186088" +} + flag { name: "multiline_search_bar" namespace: "launcher" @@ -506,3 +513,10 @@ flag { description: "Enable launcher app contrast tiles." bug: "341217082" } + +flag { + name: "msdl_feedback" + namespace: "launcher" + description: "Enable MSDL feedback for Launcher interactions" + bug: "377496684" +} \ No newline at end of file diff --git a/quickstep/res/values-night/colors.xml b/quickstep/res/values-night/colors.xml index 98e4871da2..a1e9c70f69 100644 --- a/quickstep/res/values-night/colors.xml +++ b/quickstep/res/values-night/colors.xml @@ -26,6 +26,4 @@ ?attr/materialColorPrimary - ?attr/materialColorPrimaryFixedDim - ?attr/materialColorOnPrimaryFixed \ No newline at end of file diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml index 62873d6d64..668bce764c 100644 --- a/quickstep/res/values/colors.xml +++ b/quickstep/res/values/colors.xml @@ -94,6 +94,4 @@ ?attr/materialColorPrimary - ?attr/materialColorPrimaryFixedDim - ?attr/materialColorOnPrimaryFixed \ No newline at end of file diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index 3ae2b89da4..5c80575568 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -34,7 +34,6 @@ com.android.launcher3.taskbar.TaskbarViewCallbacksFactory com.android.quickstep.LauncherRestoreEventLoggerImpl com.android.launcher3.taskbar.TaskbarEduTooltipController - com.android.quickstep.contextualeducation.SystemContextualEduStatsManager diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index ab4b1b6b5a..fa54f7cea5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -560,25 +560,25 @@ public class TaskbarManager { } } - public void checkNavBarModes() { + public void checkNavBarModes(int displayId) { if (mTaskbarActivityContext != null) { mTaskbarActivityContext.checkNavBarModes(); } } - public void finishBarAnimations() { + public void finishBarAnimations(int displayId) { if (mTaskbarActivityContext != null) { mTaskbarActivityContext.finishBarAnimations(); } } - public void touchAutoDim(boolean reset) { + public void touchAutoDim(int displayId, boolean reset) { if (mTaskbarActivityContext != null) { mTaskbarActivityContext.touchAutoDim(reset); } } - public void transitionTo(@BarTransitions.TransitionMode int barMode, + public void transitionTo(int displayId, @BarTransitions.TransitionMode int barMode, boolean animate) { if (mTaskbarActivityContext != null) { mTaskbarActivityContext.transitionTo(barMode, animate); diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java index 030a7acb48..d387794c20 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -118,7 +118,7 @@ public class AllAppsState extends LauncherState { @Override public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) { - if (launcher.getDeviceProfile().isTablet) { + if (launcher.getDeviceProfile().shouldShowAllAppsOnSheet()) { return getWorkspaceScaleAndTranslation(launcher); } else { ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW @@ -133,7 +133,7 @@ public class AllAppsState extends LauncherState { @Override protected float getDepthUnchecked(DEVICE_PROFILE_CONTEXT context) { - if (context.getDeviceProfile().isTablet) { + if (context.getDeviceProfile().shouldShowAllAppsOnSheet()) { return context.getDeviceProfile().bottomSheetDepth; } else { // The scrim fades in at approximately 50% of the swipe gesture. @@ -154,7 +154,7 @@ public class AllAppsState extends LauncherState { return new PageAlphaProvider(DECELERATE_2) { @Override public float getPageAlpha(int pageIndex) { - return launcher.getDeviceProfile().isTablet + return launcher.getDeviceProfile().shouldShowAllAppsOnSheet() ? superPageAlphaProvider.getPageAlpha(pageIndex) : 0; } @@ -164,8 +164,8 @@ public class AllAppsState extends LauncherState { @Override public int getVisibleElements(Launcher launcher) { int elements = ALL_APPS_CONTENT | FLOATING_SEARCH_BAR; - // Only add HOTSEAT_ICONS for tablets in ALL_APPS state. - if (launcher.getDeviceProfile().isTablet) { + // When All Apps is presented on a bottom sheet, HOTSEAT_ICONS are visible. + if (launcher.getDeviceProfile().shouldShowAllAppsOnSheet()) { elements |= HOTSEAT_ICONS; } return elements; @@ -202,7 +202,7 @@ public class AllAppsState extends LauncherState { @Override public int getWorkspaceScrimColor(Launcher launcher) { - return launcher.getDeviceProfile().isTablet + return launcher.getDeviceProfile().shouldShowAllAppsOnSheet() ? launcher.getResources().getColor(R.color.widgets_picker_scrim) : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor); } diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 0b6794c15f..0ea128aaf3 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -201,8 +201,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn // Only finish if the end target is RECENTS. Otherwise, if the target is // NEW_TASK, startActivityFromRecents will be skipped. if (mLastGestureState.getEndTarget() == RECENTS) { - finishRunningRecentsAnimation(false /* toHome */, - true /* forceFinish */, null /* forceFinishCb */); + finishRunningRecentsAnimation(false /* toHome */); } }); } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index e8f38be88b..5b085d2185 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -342,36 +342,36 @@ public class TouchInteractionService extends Service { @BinderThread @Override - public void checkNavBarModes() { - MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> - executeForTaskbarManager(TaskbarManager::checkNavBarModes) - )); - } - - @BinderThread - @Override - public void finishBarAnimations() { - MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> - executeForTaskbarManager(TaskbarManager::finishBarAnimations) - )); - } - - @BinderThread - @Override - public void touchAutoDim(boolean reset) { - MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> - executeForTaskbarManager(taskbarManager -> taskbarManager.touchAutoDim(reset)) - )); - } - - @BinderThread - @Override - public void transitionTo(@BarTransitions.TransitionMode int barMode, - boolean animate) { + public void checkNavBarModes(int displayId) { MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> executeForTaskbarManager( - taskbarManager -> taskbarManager.transitionTo(barMode, animate)) - )); + taskbarManager -> taskbarManager.checkNavBarModes(displayId)))); + } + + @BinderThread + @Override + public void finishBarAnimations(int displayId) { + MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService( + tis -> executeForTaskbarManager( + taskbarManager -> taskbarManager.finishBarAnimations(displayId)))); + } + + @BinderThread + @Override + public void touchAutoDim(int displayId, boolean reset) { + MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService( + tis -> executeForTaskbarManager( + taskbarManager -> taskbarManager.touchAutoDim(displayId, reset)))); + } + + @BinderThread + @Override + public void transitionTo(int displayId, @BarTransitions.TransitionMode int barMode, + boolean animate) { + MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService( + tis -> executeForTaskbarManager( + taskbarManager -> taskbarManager.transitionTo(displayId, barMode, + animate)))); } @BinderThread diff --git a/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java b/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java index d470b88d44..6a725370ba 100644 --- a/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java +++ b/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java @@ -16,29 +16,28 @@ package com.android.quickstep.contextualeducation; -import android.content.Context; - import com.android.launcher3.contextualeducation.ContextualEduStatsManager; +import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.quickstep.SystemUiProxy; import com.android.systemui.contextualeducation.GestureType; +import javax.inject.Inject; + /** * A class to update contextual education data via {@link SystemUiProxy} */ +@LauncherAppSingleton public class SystemContextualEduStatsManager extends ContextualEduStatsManager { - private Context mContext; + private final SystemUiProxy mSystemUiProxy; - public SystemContextualEduStatsManager(Context context) { - mContext = context; + @Inject + public SystemContextualEduStatsManager(SystemUiProxy systemUiProxy) { + mSystemUiProxy = systemUiProxy; } @Override public void updateEduStats(boolean isTrackpadGesture, GestureType gestureType) { - SystemUiProxy.INSTANCE.get(mContext).updateContextualEduStats(isTrackpadGesture, + mSystemUiProxy.updateContextualEduStats(isTrackpadGesture, gestureType.name()); } - - @Override - public void close() { - } } diff --git a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java index 3870b9b4c4..9f6360b1a3 100644 --- a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java +++ b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java @@ -15,10 +15,12 @@ */ package com.android.quickstep.dagger; +import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.uioverrides.SystemApiWrapper; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl; import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.PluginManagerWrapper; +import com.android.quickstep.contextualeducation.SystemContextualEduStatsManager; import dagger.Binds; import dagger.Module; @@ -28,4 +30,6 @@ public abstract class QuickStepModule { @Binds abstract PluginManagerWrapper bindPluginManagerWrapper(PluginManagerWrapperImpl impl); @Binds abstract ApiWrapper bindApiWrapper(SystemApiWrapper systemApiWrapper); + @Binds abstract ContextualEduStatsManager bindContextualEduStatsManager( + SystemContextualEduStatsManager manager); } diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt index 78224aed11..843ef6cb63 100644 --- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt +++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt @@ -218,6 +218,11 @@ class RecentsWindowManager(context: Context) : ) } + private val onBackInvokedCallback: () -> Unit = { + // If we are in live tile mode, launch the live task, otherwise return home + recentsView?.runningTaskView?.launchWithAnimation() ?: startHome() + } + private fun cleanupRecentsWindow() { RecentsWindowProtoLogProxy.logCleanup(isShowing()) if (isShowing()) { @@ -241,6 +246,10 @@ class RecentsWindowManager(context: Context) : } windowManager.addView(windowView, windowLayoutParams) + windowView + ?.findOnBackInvokedDispatcher() + ?.registerSystemOnBackInvokedCallback(onBackInvokedCallback) + windowView?.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt index c3d865f7ea..32b5b859ae 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt @@ -23,6 +23,7 @@ import com.android.launcher3.R import com.android.launcher3.dagger.LauncherAppComponent import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.util.LauncherModelHelper +import com.android.quickstep.dagger.QuickStepModule import com.android.systemui.contextualeducation.GestureType import com.android.systemui.shared.system.InputConsumerController import dagger.BindsInstance @@ -105,7 +106,7 @@ class LauncherSwipeHandlerV2Test { } @LauncherAppSingleton -@Component +@Component(modules = [QuickStepModule::class]) interface TestComponent : LauncherAppComponent { @Component.Builder interface Builder : LauncherAppComponent.Builder { diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt b/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt index 2a8afbf682..120a89b0f8 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt @@ -104,28 +104,36 @@ class TaplTestsOverviewDesktop : AbstractLauncherUiTest() { @Test @PortraitLandscape - fun dismissFocusedTask_thenDesktopTask_thenFocusedTaskIsCentered() { + fun dismissTasks_whenDesktopTask_IsInTheCenter() { // Create extra activity to be DesktopTaskView startTestActivity(TEST_ACTIVITY_EXTRA) mLauncher.goHome().switchToOverview() + val desktop = moveTaskToDesktop(TEST_ACTIVITY_EXTRA) + var overview = desktop.switchToOverview() - val overview = desktop.switchToOverview() + // Open focused task and go back to Overview to validate whether it has adjacent tasks in + // its both sides (grid task on left and desktop tasks at its right side) + val focusedTaskOpened = overview.getTestActivityTask(TEST_ACTIVITY_2).open() - // Dismiss focused task - val focusedTask1 = overview.getTestActivityTask(TEST_ACTIVITY_2) - assertTaskContentDescription(focusedTask1, TEST_ACTIVITY_2) - focusedTask1.dismiss() - - // Dismiss DesktopTaskView + // Fling to desktop task and dismiss the focused task to check repositioning of + // grid tasks. + overview = focusedTaskOpened.switchToOverview().apply { flingBackward() } val desktopTask = overview.currentTask assertWithMessage("The current task is not a Desktop.").that(desktopTask.isDesktop).isTrue() + + // Get focused task (previously opened task) then dismiss this task + val focusedTaskInOverview = overview.getTestActivityTask(TEST_ACTIVITY_2) + assertTaskContentDescription(focusedTaskInOverview, TEST_ACTIVITY_2) + focusedTaskInOverview.dismiss() + + // Dismiss DesktopTask to validate whether the new focused task will take its position desktopTask.dismiss() - // Dismiss focused task - val focusedTask2 = overview.currentTask - assertTaskContentDescription(focusedTask2, TEST_ACTIVITY_1) - focusedTask2.dismiss() + // Dismiss last focused task + val lastFocusedTask = overview.currentTask + assertTaskContentDescription(lastFocusedTask, TEST_ACTIVITY_1) + lastFocusedTask.dismiss() assertWithMessage("Still have tasks after dismissing all the tasks") .that(mLauncher.workspace.switchToOverview().hasTasks()) diff --git a/res/drawable/ic_corp_off.xml b/res/drawable/ic_corp_off.xml index 117258e3bd..d4bb2f31a9 100644 --- a/res/drawable/ic_corp_off.xml +++ b/res/drawable/ic_corp_off.xml @@ -16,9 +16,9 @@ android:width="24dp" android:height="24dp" android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?android:attr/textColorHint"> + android:viewportHeight="24"> - \ No newline at end of file + android:pathData="M16,6H20C21.11,6 22,6.89 22,8V18.99C22,19.021 21.994,19.05 21.989,19.077C21.984,19.102 21.98,19.126 21.98,19.15L20,17.17V8H10.83L8,5.17V4C8,2.89 8.89,2 10,2H14C15.11,2 16,2.89 16,4V6ZM10,6H14V4H10V6ZM19,19L8,8L6,6L2.81,2.81L1.39,4.22L3.3,6.13C2.54,6.41 2.01,7.14 2.01,8L2,19C2,20.11 2.89,21 4,21H18.17L19.78,22.61L21.19,21.2L20.82,20.83L19,19ZM4,8V19H16.17L5.17,8H4Z" + android:fillColor="?attr/materialColorOnPrimary" + android:fillType="evenOdd"/> + diff --git a/res/drawable/ic_schedule.xml b/res/drawable/ic_schedule.xml new file mode 100644 index 0000000000..3eeb6a2c2e --- /dev/null +++ b/res/drawable/ic_schedule.xml @@ -0,0 +1,25 @@ + + + + diff --git a/res/drawable/work_mode_fab_background.xml b/res/drawable/work_mode_fab_background.xml index fd948d1445..5bad965401 100644 --- a/res/drawable/work_mode_fab_background.xml +++ b/res/drawable/work_mode_fab_background.xml @@ -18,7 +18,7 @@ - + diff --git a/res/drawable/work_scheduler_background.xml b/res/drawable/work_scheduler_background.xml new file mode 100644 index 0000000000..6bbf029fc4 --- /dev/null +++ b/res/drawable/work_scheduler_background.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml index fc59e568d3..46f2d8aa42 100644 --- a/res/layout/work_mode_fab.xml +++ b/res/layout/work_mode_fab.xml @@ -12,11 +12,9 @@ See the License for the specific language governing permissions and limitations under the License. --> - - + diff --git a/res/layout/work_mode_utility_view.xml b/res/layout/work_mode_utility_view.xml new file mode 100644 index 0000000000..fc112ce849 --- /dev/null +++ b/res/layout/work_mode_utility_view.xml @@ -0,0 +1,32 @@ + + + + + diff --git a/res/values-night-v31/colors.xml b/res/values-night-v31/colors.xml index 0f630e5860..d9f9769f94 100644 --- a/res/values-night-v31/colors.xml +++ b/res/values-night-v31/colors.xml @@ -53,10 +53,5 @@ @android:color/system_accent1_800 - - @android:color/system_accent1_200 - - @android:color/system_accent1_900 - @android:color/system_neutral1_100 \ No newline at end of file diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml index a5cdfc7a1d..d74e3087c2 100644 --- a/res/values-v31/colors.xml +++ b/res/values-v31/colors.xml @@ -104,11 +104,6 @@ @android:color/system_accent1_0 - - @android:color/system_accent1_200 - - @android:color/system_accent1_900 - @android:color/system_neutral1_1000 @android:color/system_neutral1_900 diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 16ea0cd11e..4dddb9a506 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -268,6 +268,9 @@ defaults to @dimen/taskbar_button_margin_default --> + + + diff --git a/res/values/colors.xml b/res/values/colors.xml index 1eca88d009..fa1626ea80 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -98,8 +98,6 @@ #40484D ?android:attr/colorAccent - #A8C7FA - #041E49 #EFEDED #FAF9F8 diff --git a/res/values/config.xml b/res/values/config.xml index a1ccb67a57..f6f3c9563f 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -76,7 +76,6 @@ - diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 037687dec1..d4773c3c9f 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -166,6 +166,9 @@ 16dp 20dp 16dp + 16dp + 8dp + 56dp 20dp 16dp 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index d918698d1f..746bd7eb74 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -466,6 +466,8 @@ Got it \u24D8 + + Work apps are paused @@ -484,6 +486,8 @@ Pause work apps Unpause + + Work apps schedule Filter diff --git a/res/xml/backupscheme.xml b/res/xml/backupscheme.xml index 27fddc81d3..58916a8b76 100644 --- a/res/xml/backupscheme.xml +++ b/res/xml/backupscheme.xml @@ -2,6 +2,7 @@ + diff --git a/res/xml/default_workspace_5x8.xml b/res/xml/default_workspace_5x8.xml new file mode 100644 index 0000000000..b078cfd7f8 --- /dev/null +++ b/res/xml/default_workspace_5x8.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/xml/paddings_5x8.xml b/res/xml/paddings_5x8.xml new file mode 100644 index 0000000000..afa70c59bc --- /dev/null +++ b/res/xml/paddings_5x8.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 4305703fba..c25e8fb1a5 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -827,7 +827,7 @@ public class DeviceProfile { hotseatBorderSpace = cellLayoutBorderSpacePx.y; } - if (isTablet) { + if (shouldShowAllAppsOnSheet()) { allAppsPadding.top = mInsets.top; allAppsShiftRange = heightPx; } else { @@ -1516,6 +1516,11 @@ public class DeviceProfile { } } + /** Whether All Apps should be presented on a bottom sheet. */ + public boolean shouldShowAllAppsOnSheet() { + return isTablet || Flags.allAppsSheetForHandheld(); + } + private void setupAllAppsStyle(Context context) { TypedArray allAppsStyle = context.obtainStyledAttributes( inv.allAppsStyle != INVALID_RESOURCE_HANDLE ? inv.allAppsStyle diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 7acba753ff..7112a1bfb1 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -52,7 +52,6 @@ import androidx.core.content.res.ResourcesCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.DotRenderer; -import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.DeviceGridState; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.testing.shared.ResourceUtils; @@ -303,35 +302,6 @@ public class InvariantDeviceProfile implements SafeCloseable { DisplayController.INSTANCE.executeIfCreated(dc -> dc.setPriorityListener(null)); } - /** - * Reinitialize the current grid after a restore, where some grids might now be disabled. - */ - public void reinitializeAfterRestore(Context context) { - String currentGridName = getCurrentGridName(context); - String currentDbFile = dbFile; - String newGridName = initGrid(context, currentGridName); - String newDbFile = dbFile; - FileLog.d(TAG, "Reinitializing grid after restore." - + " currentGridName=" + currentGridName - + ", currentDbFile=" + currentDbFile - + ", newGridName=" + newGridName - + ", newDbFile=" + newDbFile); - if (!newDbFile.equals(currentDbFile)) { - FileLog.d(TAG, "Restored grid is disabled : " + currentGridName - + ", migrating to: " + newGridName - + ", removing all other grid db files"); - for (String gridDbFile : LauncherFiles.GRID_DB_FILES) { - if (gridDbFile.equals(currentDbFile)) { - continue; - } - if (context.getDatabasePath(gridDbFile).delete()) { - FileLog.d(TAG, "Removed old grid db file: " + gridDbFile); - } - } - setCurrentGrid(context, newGridName); - } - } - public static String getCurrentGridName(Context context) { return LauncherPrefs.get(context).get(GRID_NAME); } @@ -540,7 +510,7 @@ public class InvariantDeviceProfile implements SafeCloseable { } } - private List getPredefinedDeviceProfiles(Context context, + private static List getPredefinedDeviceProfiles(Context context, String gridName, @DeviceType int deviceType, boolean allowDisabledGrid) { ArrayList profiles = new ArrayList<>(); @@ -554,7 +524,7 @@ public class InvariantDeviceProfile implements SafeCloseable { GridOption gridOption = new GridOption(context, Xml.asAttributeSet(parser)); if ((gridOption.isEnabled(deviceType) || allowDisabledGrid) - && (Flags.oneGridSpecs() == gridOption.isNewGridOption())) { + && gridOption.filterByFlag(deviceType)) { final int displayDepth = parser.getDepth(); while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > displayDepth) @@ -710,7 +680,7 @@ public class InvariantDeviceProfile implements SafeCloseable { return parseAllDefinedGridOptions(context) .stream() .filter(go -> go.isEnabled(deviceType)) - .filter(go -> (Flags.oneGridSpecs() == go.isNewGridOption())) + .filter(go -> go.filterByFlag(deviceType)) .collect(Collectors.toList()); } @@ -967,6 +937,7 @@ public class InvariantDeviceProfile implements SafeCloseable { private final int demoModeLayoutId; private final boolean isScalable; + private final boolean mIsDualGrid; private final int devicePaddingId; private final int mWorkspaceSpecsId; private final int mWorkspaceSpecsTwoPanelId; @@ -991,6 +962,7 @@ public class InvariantDeviceProfile implements SafeCloseable { DEVICE_CATEGORY_ALL); mRowCountSpecsId = a.getResourceId( R.styleable.GridDisplayOption_rowCountSpecsId, INVALID_RESOURCE_HANDLE); + mIsDualGrid = a.getBoolean(R.styleable.GridDisplayOption_isDualGrid, false); if (mRowCountSpecsId != INVALID_RESOURCE_HANDLE) { ResourceHelper resourceHelper = new ResourceHelper(context, mRowCountSpecsId); NumRows numR = getRowCount(resourceHelper, context, deviceCategory); @@ -1154,6 +1126,13 @@ public class InvariantDeviceProfile implements SafeCloseable { public boolean isNewGridOption() { return mRowCountSpecsId != INVALID_RESOURCE_HANDLE; } + + public boolean filterByFlag(int deviceType) { + if (deviceType == TYPE_TABLET) { + return Flags.oneGridRotationHandling() == mIsDualGrid; + } + return Flags.oneGridSpecs() == isNewGridOption(); + } } public static final class NumRows { diff --git a/src/com/android/launcher3/LauncherFiles.java b/src/com/android/launcher3/LauncherFiles.java index 1148f7929c..95c0ee8680 100644 --- a/src/com/android/launcher3/LauncherFiles.java +++ b/src/com/android/launcher3/LauncherFiles.java @@ -16,6 +16,7 @@ public class LauncherFiles { private static final String XML = ".xml"; public static final String LAUNCHER_DB = "launcher.db"; + public static final String LAUNCHER_5_BY_8_DB = "launcher_5_by_8.db"; public static final String LAUNCHER_6_BY_5_DB = "launcher_6_by_5.db"; public static final String LAUNCHER_4_BY_5_DB = "launcher_4_by_5.db"; public static final String LAUNCHER_4_BY_6_DB = "launcher_4_by_6.db"; @@ -35,6 +36,7 @@ public class LauncherFiles { public static final List GRID_DB_FILES = Collections.unmodifiableList(Arrays.asList( LAUNCHER_DB, + LAUNCHER_5_BY_8_DB, LAUNCHER_6_BY_5_DB, LAUNCHER_4_BY_5_DB, LAUNCHER_4_BY_6_DB, diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 102189b530..7d5e481432 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -375,8 +375,14 @@ public abstract class LauncherState implements BaseState { } public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) { - if ((this != NORMAL && this != HINT_STATE) - || !launcher.getDeviceProfile().shouldFadeAdjacentWorkspaceScreens()) { + DeviceProfile dp = launcher.getDeviceProfile(); + boolean shouldFadeAdjacentScreens = (this == NORMAL || this == HINT_STATE) + && dp.shouldFadeAdjacentWorkspaceScreens(); + // Avoid showing adjacent screens behind handheld All Apps sheet. + if (Flags.allAppsSheetForHandheld() && dp.isPhone && this == ALL_APPS) { + shouldFadeAdjacentScreens = true; + } + if (!shouldFadeAdjacentScreens) { return DEFAULT_ALPHA_PROVIDER; } final int centerPage = launcher.getWorkspace().getNextPage(); diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index 0dd2791f5b..fc8465d59d 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -47,7 +47,6 @@ import android.os.Parcelable; import android.os.Process; import android.os.UserManager; import android.util.AttributeSet; -import android.util.FloatProperty; import android.util.Log; import android.util.SparseArray; import android.view.KeyEvent; @@ -115,19 +114,6 @@ public class ActivityAllAppsContainerView ScrimView.ScrimDrawingController { - public static final FloatProperty> BOTTOM_SHEET_ALPHA = - new FloatProperty<>("bottomSheetAlpha") { - @Override - public Float get(ActivityAllAppsContainerView containerView) { - return containerView.mBottomSheetAlpha; - } - - @Override - public void setValue(ActivityAllAppsContainerView containerView, float v) { - containerView.setBottomSheetAlpha(v); - } - }; - public static final float PULL_MULTIPLIER = .02f; public static final float FLING_VELOCITY_MULTIPLIER = 1200f; protected static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page"; @@ -191,8 +177,6 @@ public class ActivityAllAppsContainerView private ScrimView mScrimView; private int mHeaderColor; private int mBottomSheetBackgroundColor; - private float mBottomSheetAlpha = 1f; - private boolean mForceBottomSheetVisible; private int mTabsProtectionAlpha; @Nullable private AllAppsTransitionController mAllAppsTransitionController; @@ -351,20 +335,6 @@ public class ActivityAllAppsContainerView return mSearchUiManager; } - public View getBottomSheetBackground() { - return mBottomSheetBackground; - } - - /** - * Temporarily force the bottom sheet to be visible on non-tablets. - * - * @param force {@code true} means bottom sheet will be visible on phones until {@code reset()}. - */ - public void forceBottomSheetVisible(boolean force) { - mForceBottomSheetVisible = force; - updateBackgroundVisibility(mActivityContext.getDeviceProfile()); - } - public View getSearchView() { return mSearchContainer; } @@ -496,7 +466,7 @@ public class ActivityAllAppsContainerView if (mHeader != null && mHeader.getVisibility() == VISIBLE) { mHeader.reset(animate); } - forceBottomSheetVisible(false); + updateBackgroundVisibility(mActivityContext.getDeviceProfile()); // Reset the base recycler view after transitioning home. updateHeaderScroll(0); if (exitSearch) { @@ -726,7 +696,7 @@ public class ActivityAllAppsContainerView post(() -> mAH.get(AdapterHolder.WORK).applyPadding()); } else { - mWorkManager.detachWorkModeSwitch(); + mWorkManager.detachWorkUtilityViews(); mViewPager = null; } @@ -1002,18 +972,13 @@ public class ActivityAllAppsContainerView } protected void updateBackgroundVisibility(DeviceProfile deviceProfile) { - boolean visible = deviceProfile.isTablet || mForceBottomSheetVisible; - mBottomSheetBackground.setVisibility(visible ? View.VISIBLE : View.GONE); - // Note: For tablets, the opaque background and header protection are added in drawOnScrim. + mBottomSheetBackground.setVisibility( + deviceProfile.shouldShowAllAppsOnSheet() ? View.VISIBLE : View.GONE); + // Note: The opaque sheet background and header protection are added in drawOnScrim. // For the taskbar entrypoint, the scrim is drawn by its abstract slide in view container, // so its header protection is derived from this scrim instead. } - private void setBottomSheetAlpha(float alpha) { - // Bottom sheet alpha is always 1 for tablets. - mBottomSheetAlpha = mActivityContext.getDeviceProfile().isTablet ? 1f : alpha; - } - @VisibleForTesting public void onAppsUpdated() { mHasWorkApps = Stream.of(mAllAppsStore.getApps()) @@ -1151,8 +1116,8 @@ public class ActivityAllAppsContainerView applyAdapterSideAndBottomPaddings(grid); MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams(); - // Ignore left/right insets on tablet because we are already centered in-screen. - if (grid.isTablet) { + // Ignore left/right insets on bottom sheet because we are already centered in-screen. + if (grid.shouldShowAllAppsOnSheet()) { mlp.leftMargin = mlp.rightMargin = 0; } else { mlp.leftMargin = insets.left; @@ -1257,8 +1222,8 @@ public class ActivityAllAppsContainerView /** Called in Launcher#bindStringCache() to update the UI when cache is updated. */ public void updateWorkUI() { setDeviceManagementResources(); - if (mWorkManager.getWorkModeSwitch() != null) { - mWorkManager.getWorkModeSwitch().updateStringFromCache(); + if (mWorkManager.getWorkUtilityView() != null) { + mWorkManager.getWorkUtilityView().updateStringFromCache(); } inflateWorkCardsIfNeeded(); } @@ -1398,7 +1363,7 @@ public class ActivityAllAppsContainerView // Draw full background panel for tablets. if (hasBottomSheet) { mHeaderPaint.setColor(mBottomSheetBackgroundColor); - mHeaderPaint.setAlpha((int) (255 * mBottomSheetAlpha)); + mHeaderPaint.setAlpha(255); mTmpRectF.set( leftWithScale, @@ -1581,8 +1546,8 @@ public class ActivityAllAppsContainerView void applyPadding() { if (mRecyclerView != null) { int bottomOffset = 0; - if (isWork() && mWorkManager.getWorkModeSwitch() != null) { - bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight(); + if (isWork() && mWorkManager.getWorkUtilityView() != null) { + bottomOffset = mInsets.bottom + mWorkManager.getWorkUtilityView().getHeight(); } else if (isMain() && mPrivateProfileManager != null) { Optional privateSpaceHeaderItem = mAppsList.getAdapterItems() .stream() diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index c6852e015c..bd604eb08b 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -16,7 +16,6 @@ package com.android.launcher3.allapps; import static com.android.app.animation.Interpolators.DECELERATE_1_7; -import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; @@ -28,7 +27,6 @@ import static com.android.launcher3.UtilitiesKt.CLIP_CHILDREN_FALSE_MODIFIER; import static com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree; import static com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree; import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_BOTTOM_SHEET_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV; @@ -106,7 +104,7 @@ public class AllAppsTransitionController @Override public Float get(AllAppsTransitionController controller) { - if (controller.mIsTablet) { + if (controller.mShouldShowAllAppsOnSheet) { return controller.mAppsView.getActiveRecyclerView().getTranslationY(); } else { return controller.getAppsViewPullbackTranslationY().getValue(); @@ -115,7 +113,7 @@ public class AllAppsTransitionController @Override public void setValue(AllAppsTransitionController controller, float translation) { - if (controller.mIsTablet) { + if (controller.mShouldShowAllAppsOnSheet) { controller.mAppsView.getActiveRecyclerView().setTranslationY(translation); controller.getAppsViewPullbackTranslationY().setValue( ALL_APPS_PULL_BACK_TRANSLATION_DEFAULT); @@ -134,7 +132,7 @@ public class AllAppsTransitionController @Override public Float get(AllAppsTransitionController controller) { - if (controller.mIsTablet) { + if (controller.mShouldShowAllAppsOnSheet) { return controller.mAppsView.getActiveRecyclerView().getAlpha(); } else { return controller.getAppsViewPullbackAlpha().getValue(); @@ -143,7 +141,7 @@ public class AllAppsTransitionController @Override public void setValue(AllAppsTransitionController controller, float alpha) { - if (controller.mIsTablet) { + if (controller.mShouldShowAllAppsOnSheet) { controller.mAppsView.getActiveRecyclerView().setAlpha(alpha); controller.getAppsViewPullbackAlpha().setValue( ALL_APPS_PULL_BACK_ALPHA_DEFAULT); @@ -168,6 +166,7 @@ public class AllAppsTransitionController @Nullable private Animator.AnimatorListener mAllAppsSearchBackAnimationListener; private boolean mIsVerticalLayout; + private boolean mShouldShowAllAppsOnSheet; // Animation in this class is controlled by a single variable {@link mProgress}. // Visually, it represents top y coordinate of the all apps container if multiplied with @@ -183,8 +182,6 @@ public class AllAppsTransitionController private MultiValueAlpha mAppsViewAlpha; private MultiPropertyFactory mAppsViewTranslationY; - private boolean mIsTablet; - private boolean mHasScaleEffect; private final VibratorWrapper mVibratorWrapper; @@ -193,7 +190,7 @@ public class AllAppsTransitionController DeviceProfile dp = mLauncher.getDeviceProfile(); mProgress = 1f; mIsVerticalLayout = dp.isVerticalBarLayout(); - mIsTablet = dp.isTablet; + mShouldShowAllAppsOnSheet = dp.shouldShowAllAppsOnSheet(); mNavScrimFlag = Themes.getAttrBoolean(l, R.attr.isMainColorDark) ? FLAG_DARK_NAV : FLAG_LIGHT_NAV; @@ -217,7 +214,7 @@ public class AllAppsTransitionController mLauncher.getWorkspace().getPageIndicator().setTranslationY(0); } - mIsTablet = dp.isTablet; + mShouldShowAllAppsOnSheet = dp.shouldShowAllAppsOnSheet(); } /** @@ -395,10 +392,6 @@ public class AllAppsTransitionController setter.setFloat(getAppsViewPullbackAlpha(), MultiPropertyFactory.MULTI_PROPERTY_VALUE, hasAllAppsContent ? 1 : 0, allAppsFade); - setter.setFloat(mLauncher.getAppsView(), - ActivityAllAppsContainerView.BOTTOM_SHEET_ALPHA, hasAllAppsContent ? 1 : 0, - config.getInterpolator(ANIM_ALL_APPS_BOTTOM_SHEET_FADE, INSTANT)); - boolean shouldProtectHeader = !config.hasAnimationFlag(StateAnimationConfig.SKIP_SCRIM) && (ALL_APPS == state || mLauncher.getStateManager().getState() == ALL_APPS); mScrimView.setDrawingController(shouldProtectHeader ? mAppsView : null); diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java index 96998a3e38..3d0c1d063d 100644 --- a/src/com/android/launcher3/allapps/WorkProfileManager.java +++ b/src/com/android/launcher3/allapps/WorkProfileManager.java @@ -58,7 +58,7 @@ public class WorkProfileManager extends UserProfileManager implements PersonalWorkSlidingTabStrip.OnActivePageChangedListener { private static final String TAG = "WorkProfileManager"; private final ActivityAllAppsContainerView mAllApps; - private WorkModeSwitch mWorkModeSwitch; + private WorkUtilityView mWorkUtilityView; private final Predicate mWorkProfileMatcher; public WorkProfileManager( @@ -79,15 +79,15 @@ public class WorkProfileManager extends UserProfileManager @Override public void onActivePageChanged(int page) { - updateWorkFAB(page); + updateWorkUtilityViews(page); } - private void updateWorkFAB(int page) { - if (mWorkModeSwitch != null) { + private void updateWorkUtilityViews(int page) { + if (mWorkUtilityView != null) { if (page == MAIN || page == SEARCH) { - mWorkModeSwitch.animateVisibility(false); + mWorkUtilityView.animateVisibility(false); } else if (page == WORK && getCurrentState() == STATE_ENABLED) { - mWorkModeSwitch.animateVisibility(true); + mWorkUtilityView.animateVisibility(true); } } } @@ -104,10 +104,10 @@ public class WorkProfileManager extends UserProfileManager } boolean isEnabled = !mAllApps.getAppsStore().hasModelFlag(quietModeFlag); updateCurrentState(isEnabled ? STATE_ENABLED : STATE_DISABLED); - if (mWorkModeSwitch != null) { + if (mWorkUtilityView != null) { // reset the position of the button and clear IME insets. - mWorkModeSwitch.getImeInsets().setEmpty(); - mWorkModeSwitch.updateTranslationY(); + mWorkUtilityView.getImeInsets().setEmpty(); + mWorkUtilityView.updateTranslationY(); } } @@ -116,54 +116,54 @@ public class WorkProfileManager extends UserProfileManager if (getAH() != null) { getAH().mAppsList.updateAdapterItems(); } - if (mWorkModeSwitch != null) { - updateWorkFAB(mAllApps.getCurrentPage()); + if (mWorkUtilityView != null) { + updateWorkUtilityViews(mAllApps.getCurrentPage()); } if (getCurrentState() == STATE_ENABLED) { - attachWorkModeSwitch(); + attachWorkUtilityViews(); } else if (getCurrentState() == STATE_DISABLED) { - detachWorkModeSwitch(); + detachWorkUtilityViews(); } } /** * Creates and attaches for profile toggle button to {@link ActivityAllAppsContainerView} */ - public boolean attachWorkModeSwitch() { + public boolean attachWorkUtilityViews() { if (!mAllApps.getAppsStore().hasModelFlag( FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION)) { Log.e(TAG, "unable to attach work mode switch; Missing required permissions"); return false; } - if (mWorkModeSwitch == null) { - mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate( - R.layout.work_mode_fab, mAllApps, false); + if (mWorkUtilityView == null) { + mWorkUtilityView = (WorkUtilityView) mAllApps.getLayoutInflater().inflate( + R.layout.work_mode_utility_view, mAllApps, false); } - if (mWorkModeSwitch.getParent() == null) { - mAllApps.addView(mWorkModeSwitch); + if (mWorkUtilityView.getParent() == null) { + mAllApps.addView(mWorkUtilityView); } if (mAllApps.getCurrentPage() != WORK) { - mWorkModeSwitch.animateVisibility(false); + mWorkUtilityView.animateVisibility(false); } if (getAH() != null) { getAH().applyPadding(); } - mWorkModeSwitch.setOnClickListener(this::onWorkFabClicked); + mWorkUtilityView.setOnClickListener(this::onWorkFabClicked); return true; } /** * Removes work profile toggle button from {@link ActivityAllAppsContainerView} */ - public void detachWorkModeSwitch() { - if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) { - mAllApps.removeView(mWorkModeSwitch); + public void detachWorkUtilityViews() { + if (mWorkUtilityView != null && mWorkUtilityView.getParent() == mAllApps) { + mAllApps.removeView(mWorkUtilityView); } - mWorkModeSwitch = null; + mWorkUtilityView = null; } @Nullable - public WorkModeSwitch getWorkModeSwitch() { - return mWorkModeSwitch; + public WorkUtilityView getWorkUtilityView() { + return mWorkUtilityView; } private ActivityAllAppsContainerView.AdapterHolder getAH() { @@ -199,7 +199,7 @@ public class WorkProfileManager extends UserProfileManager } private void onWorkFabClicked(View view) { - if (getCurrentState() == STATE_ENABLED && mWorkModeSwitch.isEnabled()) { + if (getCurrentState() == STATE_ENABLED && mWorkUtilityView.isEnabled()) { logEvents(LAUNCHER_TURN_OFF_WORK_APPS_TAP); setWorkProfileEnabled(false); } @@ -216,7 +216,7 @@ public class WorkProfileManager extends UserProfileManager } @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - WorkModeSwitch fab = getWorkModeSwitch(); + WorkUtilityView fab = getWorkUtilityView(); if (fab == null){ return; } diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkUtilityView.java similarity index 65% rename from src/com/android/launcher3/allapps/WorkModeSwitch.java rename to src/com/android/launcher3/allapps/WorkUtilityView.java index f1f72b267b..4b58ab06dc 100644 --- a/src/com/android/launcher3/allapps/WorkModeSwitch.java +++ b/src/com/android/launcher3/allapps/WorkUtilityView.java @@ -21,11 +21,13 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; +import android.content.Intent; import android.graphics.Rect; import android.text.TextUtils; import android.util.AttributeSet; import android.view.ViewGroup; import android.view.WindowInsets; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -36,6 +38,7 @@ import androidx.core.view.WindowInsetsCompat; import com.android.app.animation.Interpolators; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Flags; import com.android.launcher3.Insettable; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -43,10 +46,13 @@ import com.android.launcher3.anim.AnimatedPropertySetter; import com.android.launcher3.anim.KeyboardInsetAnimationCallback; import com.android.launcher3.model.StringCache; import com.android.launcher3.views.ActivityContext; + +import java.util.ArrayList; + /** - * Work profile toggle switch shown at the bottom of AllApps work tab + * Work profile utility ViewGroup that is shown at the bottom of AllApps work tab */ -public class WorkModeSwitch extends LinearLayout implements Insettable, +public class WorkUtilityView extends LinearLayout implements Insettable, KeyboardInsetAnimationCallback.KeyboardInsetListener { private static final int TEXT_EXPAND_OPACITY_DURATION = 300; @@ -54,10 +60,14 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, private static final int EXPAND_COLLAPSE_DURATION = 300; private static final int TEXT_ALPHA_EXPAND_DELAY = 80; private static final int TEXT_ALPHA_COLLAPSE_DELAY = 0; + private static final int WORK_SCHEDULER_OPACITY_DURATION = + (int) (EXPAND_COLLAPSE_DURATION * 0.75f); private static final int FLAG_FADE_ONGOING = 1 << 1; private static final int FLAG_TRANSLATION_ONGOING = 1 << 2; private static final int FLAG_IS_EXPAND = 1 << 3; private static final int SCROLL_THRESHOLD_DP = 10; + private static final float WORK_SCHEDULER_SCALE_MIN = 0.25f; + private static final float WORK_SCHEDULER_SCALE_MAX = 1f; private final Rect mInsets = new Rect(); private final Rect mImeInsets = new Rect(); @@ -67,22 +77,25 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, private final int mTextMarginStart; private final int mTextMarginEnd; private final int mIconMarginStart; + private final String mWorkSchedulerIntentAction; // Threshold when user scrolls up/down to determine when should button extend/collapse private final int mScrollThreshold; - private TextView mTextView; - private ImageView mIcon; private ValueAnimator mPauseFABAnim; + private TextView mPauseText; + private ImageView mWorkIcon; + private ImageButton mSchedulerButton; - public WorkModeSwitch(@NonNull Context context) { + public WorkUtilityView(@NonNull Context context) { this(context, null, 0); } - public WorkModeSwitch(@NonNull Context context, @NonNull AttributeSet attrs) { + public WorkUtilityView(@NonNull Context context, @NonNull AttributeSet attrs) { this(context, attrs, 0); } - public WorkModeSwitch(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) { + public WorkUtilityView(@NonNull Context context, @NonNull AttributeSet attrs, + int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; mScrollThreshold = Utilities.dpToPx(SCROLL_THRESHOLD_DP); @@ -93,14 +106,17 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, R.dimen.work_fab_text_end_margin); mIconMarginStart = mContext.getResources().getDimensionPixelSize( R.dimen.work_fab_icon_start_margin_expanded); + mWorkSchedulerIntentAction = mContext.getResources().getString( + R.string.work_profile_scheduler_intent); } @Override protected void onFinishInflate() { super.onFinishInflate(); - mTextView = findViewById(R.id.pause_text); - mIcon = findViewById(R.id.work_icon); + mPauseText = findViewById(R.id.pause_text); + mWorkIcon = findViewById(R.id.work_icon); + mSchedulerButton = findViewById(R.id.work_scheduler); setSelected(true); KeyboardInsetAnimationCallback keyboardInsetAnimationCallback = new KeyboardInsetAnimationCallback(this); @@ -109,6 +125,12 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, addFlag(FLAG_IS_EXPAND); setInsets(mActivityContext.getDeviceProfile().getInsets()); updateStringFromCache(); + mSchedulerButton.setVisibility(GONE); + if (shouldUseScheduler()) { + mSchedulerButton.setVisibility(VISIBLE); + mSchedulerButton.setOnClickListener(view -> + mContext.startActivity(new Intent(mWorkSchedulerIntentAction))); + } } @Override @@ -166,8 +188,10 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, WindowInsetsCompat.toWindowInsetsCompat(insets, this); if (windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime())) { setInsets(mImeInsets, windowInsetsCompat.getInsets(WindowInsetsCompat.Type.ime())); + shrink(); } else { mImeInsets.setEmpty(); + extend(); } updateTranslationY(); return super.onApplyWindowInsets(insets); @@ -183,15 +207,63 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, super.setTranslationY(Math.min(translationY, -mInsets.bottom)); } + private ValueAnimator animateSchedulerScale(boolean isExpanding) { + float scaleFrom = isExpanding ? WORK_SCHEDULER_SCALE_MIN : WORK_SCHEDULER_SCALE_MAX; + float scaleTo = isExpanding ? WORK_SCHEDULER_SCALE_MAX : WORK_SCHEDULER_SCALE_MIN; + ValueAnimator schedulerScaleAnim = ObjectAnimator.ofFloat(scaleFrom, scaleTo); + schedulerScaleAnim.setDuration(EXPAND_COLLAPSE_DURATION); + schedulerScaleAnim.setInterpolator(Interpolators.STANDARD); + schedulerScaleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + float scale = (float) valueAnimator.getAnimatedValue(); + mSchedulerButton.setScaleX(scale); + mSchedulerButton.setScaleY(scale); + } + }); + schedulerScaleAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + if (isExpanding) { + mSchedulerButton.setVisibility(VISIBLE); + } + } - private void animatePillTransition(boolean isExpanding) { + @Override + public void onAnimationEnd(Animator animation) { + if (!isExpanding) { + mSchedulerButton.setVisibility(GONE); + } + } + }); + return schedulerScaleAnim; + } + + private ValueAnimator animateSchedulerAlpha(boolean isExpanding) { + float alphaFrom = isExpanding ? 0 : 1; + float alphaTo = isExpanding ? 1 : 0; + ValueAnimator schedulerAlphaAnim = ObjectAnimator.ofFloat(alphaFrom, alphaTo); + schedulerAlphaAnim.setDuration(WORK_SCHEDULER_OPACITY_DURATION); + schedulerAlphaAnim.setStartDelay(isExpanding ? 0 : + EXPAND_COLLAPSE_DURATION - WORK_SCHEDULER_OPACITY_DURATION); + schedulerAlphaAnim.setInterpolator(Interpolators.STANDARD); + schedulerAlphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + mSchedulerButton.setAlpha((float) valueAnimator.getAnimatedValue()); + } + }); + return schedulerAlphaAnim; + } + + private void animateWorkUtilityViews(boolean isExpanding) { if (!shouldAnimate(isExpanding)) { return; } AnimatorSet animatorSet = new AnimatedPropertySetter().buildAnim(); - mTextView.measure(0,0); - int currentWidth = mTextView.getWidth(); - int fullWidth = mTextView.getMeasuredWidth(); + mPauseText.measure(0,0); + int currentWidth = mPauseText.getWidth(); + int fullWidth = mPauseText.getMeasuredWidth(); float from = isExpanding ? 0 : currentWidth; float to = isExpanding ? fullWidth : 0; mPauseFABAnim = ObjectAnimator.ofFloat(from, to); @@ -203,15 +275,15 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, float translation = (float) valueAnimator.getAnimatedValue(); float translationFraction = translation / fullWidth; ViewGroup.MarginLayoutParams textViewLayoutParams = - (ViewGroup.MarginLayoutParams) mTextView.getLayoutParams(); + (ViewGroup.MarginLayoutParams) mPauseText.getLayoutParams(); textViewLayoutParams.width = (int) translation; textViewLayoutParams.setMarginStart((int) (mTextMarginStart * translationFraction)); textViewLayoutParams.setMarginEnd((int) (mTextMarginEnd * translationFraction)); - mTextView.setLayoutParams(textViewLayoutParams); + mPauseText.setLayoutParams(textViewLayoutParams); ViewGroup.MarginLayoutParams iconLayoutParams = - (ViewGroup.MarginLayoutParams) mIcon.getLayoutParams(); + (ViewGroup.MarginLayoutParams) mWorkIcon.getLayoutParams(); iconLayoutParams.setMarginStart((int) (mIconMarginStart * translationFraction)); - mIcon.setLayoutParams(iconLayoutParams); + mWorkIcon.setLayoutParams(iconLayoutParams); } }); mPauseFABAnim.addListener(new AnimatorListenerAdapter() { @@ -220,21 +292,28 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, if (isExpanding) { addFlag(FLAG_IS_EXPAND); } else { - mTextView.setVisibility(GONE); + mPauseText.setVisibility(GONE); removeFlag(FLAG_IS_EXPAND); } - mTextView.setHorizontallyScrolling(false); - mTextView.setEllipsize(TextUtils.TruncateAt.END); + mPauseText.setHorizontallyScrolling(false); + mPauseText.setEllipsize(TextUtils.TruncateAt.END); } @Override public void onAnimationStart(Animator animator) { - mTextView.setHorizontallyScrolling(true); - mTextView.setVisibility(VISIBLE); - mTextView.setEllipsize(null); + mPauseText.setHorizontallyScrolling(true); + mPauseText.setVisibility(VISIBLE); + mPauseText.setEllipsize(null); } }); - animatorSet.playTogether(mPauseFABAnim, updatePauseTextAlpha(isExpanding)); + ArrayList animatorList = new ArrayList<>(); + animatorList.add(mPauseFABAnim); + animatorList.add(updatePauseTextAlpha(isExpanding)); + if (shouldUseScheduler()) { + animatorList.add(animateSchedulerScale(isExpanding)); + animatorList.add(animateSchedulerAlpha(isExpanding)); + } + animatorSet.playTogether(animatorList); animatorSet.start(); } @@ -250,7 +329,7 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { - mTextView.setAlpha((float) valueAnimator.getAnimatedValue()); + mPauseText.setAlpha((float) valueAnimator.getAnimatedValue()); } }); return alphaAnim; @@ -287,11 +366,11 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, } public void extend() { - animatePillTransition(true); + animateWorkUtilityViews(true); } - public void shrink(){ - animatePillTransition(false); + public void shrink() { + animateWorkUtilityViews(false); } /** @@ -310,7 +389,11 @@ public class WorkModeSwitch extends LinearLayout implements Insettable, public void updateStringFromCache(){ StringCache cache = mActivityContext.getStringCache(); if (cache != null) { - mTextView.setText(cache.workProfilePauseButton); + mPauseText.setText(cache.workProfilePauseButton); } } + + private boolean shouldUseScheduler() { + return Flags.workSchedulerInWorkProfile() && !mWorkSchedulerIntentAction.isEmpty(); + } } diff --git a/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java b/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java index da13546c78..5664174014 100644 --- a/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java +++ b/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java @@ -16,22 +16,25 @@ package com.android.launcher3.contextualeducation; -import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; - -import com.android.launcher3.R; -import com.android.launcher3.util.MainThreadInitializedObject; -import com.android.launcher3.util.ResourceBasedOverride; -import com.android.launcher3.util.SafeCloseable; +import com.android.launcher3.dagger.LauncherAppSingleton; +import com.android.launcher3.dagger.LauncherBaseAppComponent; +import com.android.launcher3.util.DaggerSingletonObject; import com.android.systemui.contextualeducation.GestureType; +import javax.inject.Inject; + /** * A class to update contextual education data. It is a no-op implementation and could be - * overridden by changing the resource value [R.string.contextual_edu_manager_class] to provide - * a real implementation. + * overridden through dagger modules to provide a real implementation. */ -public class ContextualEduStatsManager implements ResourceBasedOverride, SafeCloseable { - public static final MainThreadInitializedObject INSTANCE = - forOverride(ContextualEduStatsManager.class, R.string.contextual_edu_manager_class); +@LauncherAppSingleton +public class ContextualEduStatsManager { + public static final DaggerSingletonObject INSTANCE = + new DaggerSingletonObject<>(LauncherBaseAppComponent::getContextualEduStatsManager); + + @Inject + public ContextualEduStatsManager() { } + /** * Updates contextual education stats when a gesture is triggered @@ -40,8 +43,4 @@ public class ContextualEduStatsManager implements ResourceBasedOverride, SafeClo */ public void updateEduStats(boolean isTrackpadGesture, GestureType gestureType) { } - - @Override - public void close() { - } } diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index e89671e090..0e20f7591b 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -18,7 +18,9 @@ package com.android.launcher3.dagger; import android.content.Context; +import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.graphics.IconShape; +import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.DaggerSingletonTracker; @@ -43,9 +45,11 @@ import dagger.BindsInstance; public interface LauncherBaseAppComponent { DaggerSingletonTracker getDaggerSingletonTracker(); ApiWrapper getApiWrapper(); + ContextualEduStatsManager getContextualEduStatsManager(); CustomWidgetManager getCustomWidgetManager(); IconShape getIconShape(); InstallSessionHelper getInstallSessionHelper(); + ItemInstallQueue getItemInstallQueue(); RefreshRateTracker getRefreshRateTracker(); ScreenOnTracker getScreenOnTracker(); SettingsCache getSettingsCache(); diff --git a/src/com/android/launcher3/icons/MonochromeIconFactory.java b/src/com/android/launcher3/icons/MonochromeIconFactory.java deleted file mode 100644 index 2854d51631..0000000000 --- a/src/com/android/launcher3/icons/MonochromeIconFactory.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2022 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.icons; - -import static android.graphics.Paint.FILTER_BITMAP_FLAG; - -import android.annotation.TargetApi; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BlendMode; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.drawable.AdaptiveIconDrawable; -import android.graphics.drawable.Drawable; -import android.os.Build; - -import androidx.annotation.WorkerThread; - -import com.android.launcher3.icons.BaseIconFactory.ClippedMonoDrawable; - -import java.nio.ByteBuffer; - -/** - * Utility class to generate monochrome icons version for a given drawable. - */ -@TargetApi(Build.VERSION_CODES.TIRAMISU) -public class MonochromeIconFactory extends Drawable { - - private final Bitmap mFlatBitmap; - private final Canvas mFlatCanvas; - private final Paint mCopyPaint; - - private final Bitmap mAlphaBitmap; - private final Canvas mAlphaCanvas; - private final byte[] mPixels; - - private final int mBitmapSize; - private final int mEdgePixelLength; - - private final Paint mDrawPaint; - private final Rect mSrcRect; - - MonochromeIconFactory(int iconBitmapSize) { - float extraFactor = AdaptiveIconDrawable.getExtraInsetFraction(); - float viewPortScale = 1 / (1 + 2 * extraFactor); - mBitmapSize = Math.round(iconBitmapSize * 2 * viewPortScale); - mPixels = new byte[mBitmapSize * mBitmapSize]; - mEdgePixelLength = mBitmapSize * (mBitmapSize - iconBitmapSize) / 2; - - mFlatBitmap = Bitmap.createBitmap(mBitmapSize, mBitmapSize, Config.ARGB_8888); - mFlatCanvas = new Canvas(mFlatBitmap); - - mAlphaBitmap = Bitmap.createBitmap(mBitmapSize, mBitmapSize, Config.ALPHA_8); - mAlphaCanvas = new Canvas(mAlphaBitmap); - - mDrawPaint = new Paint(FILTER_BITMAP_FLAG); - mDrawPaint.setColor(Color.WHITE); - mSrcRect = new Rect(0, 0, mBitmapSize, mBitmapSize); - - mCopyPaint = new Paint(FILTER_BITMAP_FLAG); - mCopyPaint.setBlendMode(BlendMode.SRC); - - // Crate a color matrix which converts the icon to grayscale and then uses the average - // of RGB components as the alpha component. - ColorMatrix satMatrix = new ColorMatrix(); - satMatrix.setSaturation(0); - float[] vals = satMatrix.getArray(); - vals[15] = vals[16] = vals[17] = .3333f; - vals[18] = vals[19] = 0; - mCopyPaint.setColorFilter(new ColorMatrixColorFilter(vals)); - } - - private void drawDrawable(Drawable drawable) { - if (drawable != null) { - drawable.setBounds(0, 0, mBitmapSize, mBitmapSize); - drawable.draw(mFlatCanvas); - } - } - - /** - * Creates a monochrome version of the provided drawable - */ - @WorkerThread - public Drawable wrap(AdaptiveIconDrawable icon) { - mFlatCanvas.drawColor(Color.BLACK); - drawDrawable(icon.getBackground()); - drawDrawable(icon.getForeground()); - generateMono(); - return new ClippedMonoDrawable(this); - } - - @WorkerThread - private void generateMono() { - mAlphaCanvas.drawBitmap(mFlatBitmap, 0, 0, mCopyPaint); - - // Scale the end points: - ByteBuffer buffer = ByteBuffer.wrap(mPixels); - buffer.rewind(); - mAlphaBitmap.copyPixelsToBuffer(buffer); - - int min = 0xFF; - int max = 0; - for (byte b : mPixels) { - min = Math.min(min, b & 0xFF); - max = Math.max(max, b & 0xFF); - } - - if (min < max) { - // rescale pixels to increase contrast - float range = max - min; - - // In order to check if the colors should be flipped, we just take the average color - // of top and bottom edge which should correspond to be background color. If the edge - // colors have more opacity, we flip the colors; - int sum = 0; - for (int i = 0; i < mEdgePixelLength; i++) { - sum += (mPixels[i] & 0xFF); - sum += (mPixels[mPixels.length - 1 - i] & 0xFF); - } - float edgeAverage = sum / (mEdgePixelLength * 2f); - float edgeMapped = (edgeAverage - min) / range; - boolean flipColor = edgeMapped > .5f; - - for (int i = 0; i < mPixels.length; i++) { - int p = mPixels[i] & 0xFF; - int p2 = Math.round((p - min) * 0xFF / range); - mPixels[i] = flipColor ? (byte) (255 - p2) : (byte) (p2); - } - buffer.rewind(); - mAlphaBitmap.copyPixelsFromBuffer(buffer); - } - } - - @Override - public void draw(Canvas canvas) { - canvas.drawBitmap(mAlphaBitmap, mSrcRect, getBounds(), mDrawPaint); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - @Override - public void setAlpha(int i) { - mDrawPaint.setAlpha(i); - } - - @Override - public void setColorFilter(ColorFilter colorFilter) { - mDrawPaint.setColorFilter(colorFilter); - } -} diff --git a/src/com/android/launcher3/model/GridSizeMigrationDBController.java b/src/com/android/launcher3/model/GridSizeMigrationDBController.java index bad7577fc3..2d6be7ed10 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationDBController.java +++ b/src/com/android/launcher3/model/GridSizeMigrationDBController.java @@ -38,7 +38,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings; @@ -86,6 +85,9 @@ public class GridSizeMigrationDBController { if (needsToMigrate) { Log.i(TAG, "Migration is needed. destDeviceState: " + destDeviceState + ", srcDeviceState: " + srcDeviceState); + } else { + Log.i(TAG, "Migration is not needed. destDeviceState: " + destDeviceState + + ", srcDeviceState: " + srcDeviceState); } return needsToMigrate; } @@ -118,21 +120,13 @@ public class GridSizeMigrationDBController { @NonNull DatabaseHelper target, @NonNull SQLiteDatabase source) { - Log.i("b/360462379", "Going from " + srcDeviceState.getColumns() + "x" - + srcDeviceState.getRows()); - Log.i("b/360462379", "Going to " + destDeviceState.getColumns() + "x" - + destDeviceState.getRows()); - if (!needsToMigrate(srcDeviceState, destDeviceState)) { - Log.i("b/360462379", "Does not need to migrate."); return true; } if (LauncherPrefs.get(context).get(IS_FIRST_LOAD_AFTER_RESTORE) - && Flags.enableGridMigrationFix() && srcDeviceState.getColumns().equals(destDeviceState.getColumns()) && srcDeviceState.getRows() < destDeviceState.getRows()) { - Log.i("b/360462379", "Grid migration fix entry point."); // Only use this strategy when comparing the previous grid to the new grid and the // columns are the same and the destination has more rows copyTable(source, TABLE_NAME, target.getWritableDatabase(), TABLE_NAME, context); diff --git a/src/com/android/launcher3/model/GridSizeMigrationLogic.kt b/src/com/android/launcher3/model/GridSizeMigrationLogic.kt index 9470abf11d..07316ef0ee 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationLogic.kt +++ b/src/com/android/launcher3/model/GridSizeMigrationLogic.kt @@ -339,7 +339,7 @@ class GridSizeMigrationLogic { srcDeviceState: DeviceGridState, destDeviceState: DeviceGridState, ): Boolean { - return (isFirstLoad && Flags.enableGridMigrationFix()) && + return isFirstLoad && srcDeviceState.columns == destDeviceState.columns && srcDeviceState.rows < destDeviceState.rows } diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java index 49f75eb167..f9c6e9632b 100644 --- a/src/com/android/launcher3/model/ItemInstallQueue.java +++ b/src/com/android/launcher3/model/ItemInstallQueue.java @@ -45,16 +45,18 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.dagger.ApplicationContext; +import com.android.launcher3.dagger.LauncherAppSingleton; +import com.android.launcher3.dagger.LauncherBaseAppComponent; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; -import com.android.launcher3.util.MainThreadInitializedObject; +import com.android.launcher3.util.DaggerSingletonObject; import com.android.launcher3.util.PersistedItemArray; import com.android.launcher3.util.Preconditions; -import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import java.util.HashSet; @@ -62,10 +64,13 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.inject.Inject; + /** * Class to maintain a queue of pending items to be added to the workspace. */ -public class ItemInstallQueue implements SafeCloseable { +@LauncherAppSingleton +public class ItemInstallQueue { private static final String LOG = "ItemInstallQueue"; @@ -81,9 +86,8 @@ public class ItemInstallQueue implements SafeCloseable { public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450; public static final int NEW_SHORTCUT_STAGGER_DELAY = 85; - public static MainThreadInitializedObject INSTANCE = - new MainThreadInitializedObject<>(ItemInstallQueue::new); - + public static DaggerSingletonObject INSTANCE = + new DaggerSingletonObject<>(LauncherBaseAppComponent::getItemInstallQueue); private final PersistedItemArray mStorage = new PersistedItemArray<>(APPS_PENDING_INSTALL); private final Context mContext; @@ -95,13 +99,11 @@ public class ItemInstallQueue implements SafeCloseable { // Only accessed on worker thread private List mItems; - private ItemInstallQueue(Context context) { + @Inject + public ItemInstallQueue(@ApplicationContext Context context) { mContext = context; } - @Override - public void close() {} - @WorkerThread private void ensureQueueLoaded() { Preconditions.assertWorkerThread(); diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index 59c27af6da..8db981f26a 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -51,7 +51,6 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; -import com.android.launcher3.Flags; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherFiles; @@ -124,18 +123,14 @@ public class RestoreDbTask { // executed again. LauncherPrefs.get(context).removeSync(RESTORE_DEVICE); - if (Flags.enableNarrowGridRestore()) { - DeviceGridState deviceGridState = new DeviceGridState(context); - String oldPhoneFileName = deviceGridState.getDbFile(); - List previousDbs = existingDbs(context); - removeOldDBs(context, oldPhoneFileName); - // The idp before this contains data about the old phone, after this it becomes the idp - // of the current phone. - idp.reset(context); - trySettingPreviousGridAsCurrent(context, idp, oldPhoneFileName, previousDbs); - } else { - idp.reinitializeAfterRestore(context); - } + DeviceGridState deviceGridState = new DeviceGridState(context); + String oldPhoneFileName = deviceGridState.getDbFile(); + List previousDbs = existingDbs(context); + removeOldDBs(context, oldPhoneFileName); + // The idp before this contains data about the old phone, after this it becomes the idp + // of the current phone. + idp.reset(context); + trySettingPreviousGridAsCurrent(context, idp, oldPhoneFileName, previousDbs); } diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java index 0ca5afd1e8..2ffbbf400a 100644 --- a/src/com/android/launcher3/states/StateAnimationConfig.java +++ b/src/com/android/launcher3/states/StateAnimationConfig.java @@ -77,7 +77,6 @@ public class StateAnimationConfig { ANIM_WORKSPACE_PAGE_TRANSLATE_X, ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN, ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE, - ANIM_ALL_APPS_BOTTOM_SHEET_FADE, ANIM_ALL_APPS_KEYBOARD_FADE }) @Retention(RetentionPolicy.SOURCE) @@ -101,8 +100,7 @@ public class StateAnimationConfig { public static final int ANIM_WORKSPACE_PAGE_TRANSLATE_X = 15; public static final int ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN = 17; public static final int ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE = 18; - public static final int ANIM_ALL_APPS_BOTTOM_SHEET_FADE = 19; - public static final int ANIM_ALL_APPS_KEYBOARD_FADE = 20; + public static final int ANIM_ALL_APPS_KEYBOARD_FADE = 19; private static final int ANIM_TYPES_COUNT = 21; diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java index 9dcdf22852..107bcc1226 100644 --- a/src/com/android/launcher3/touch/AllAppsSwipeController.java +++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java @@ -198,7 +198,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { * Applies Animation config values for transition from all apps to home. */ public static void applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config) { - if (launcher.getDeviceProfile().isTablet) { + if (launcher.getDeviceProfile().shouldShowAllAppsOnSheet()) { config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.reverse(ALL_APPS_SCRIM_RESPONDER)); config.setInterpolator(ANIM_ALL_APPS_FADE, FINAL_FRAME); @@ -240,7 +240,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { */ public static void applyNormalToAllAppsAnimConfig( Launcher launcher, StateAnimationConfig config) { - if (launcher.getDeviceProfile().isTablet) { + if (launcher.getDeviceProfile().shouldShowAllAppsOnSheet()) { config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT); config.setInterpolator(ANIM_SCRIM_FADE, ALL_APPS_SCRIM_RESPONDER); if (!config.isUserControlled()) { diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java index a45e3bbb84..33ffd1dd40 100644 --- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java +++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java @@ -158,16 +158,16 @@ public class TaplWorkProfileTest extends AbstractLauncherUiTest { waitForLauncherCondition("work profile initial state check failed", launcher -> - manager.getWorkModeSwitch() != null + manager.getWorkUtilityView() != null && manager.getCurrentState() == WorkProfileManager.STATE_ENABLED - && manager.getWorkModeSwitch().isEnabled(), + && manager.getWorkUtilityView().isEnabled(), LauncherInstrumentation.WAIT_TIME_MS); //start work profile toggle OFF test executeOnLauncher(l -> { // Ensure updates are not deferred so notification happens when apps pause. l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST); - l.getAppsView().getWorkManager().getWorkModeSwitch().performClick(); + l.getAppsView().getWorkManager().getWorkUtilityView().performClick(); }); waitForLauncherCondition("Work profile toggle OFF failed", launcher -> { diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index e1bd686f65..512db394ac 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -29,6 +29,7 @@ import androidx.test.uiautomator.UiObject2; import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel; import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType; +import com.android.launcher3.tapl.OverviewTask.TaskViewType; import com.android.launcher3.testing.shared.TestProtocol; import java.util.List; @@ -121,12 +122,31 @@ public abstract class Background extends LauncherInstrumentation.VisibleContaine if (mLauncher.isTablet()) { List tasks = mLauncher.getDevice().findObjects( TASK_SELECTOR); + final int centerX = mLauncher.getDevice().getDisplayWidth() / 2; - mLauncher.assertTrue( - "Task(s) found to the right of the swiped task", - tasks.stream().allMatch(t -> - t.getVisibleBounds().right < centerX - || t.getVisibleBounds().centerX() == centerX)); + UiObject2 centerTask = tasks.stream() + .filter(t -> t.getVisibleCenter().x == centerX) + .findFirst() + .orElse(null); + + if (centerTask != null) { + mLauncher.assertTrue( + "Task(s) found to the right of the swiped task", + tasks.stream() + .filter(t -> t != centerTask + && OverviewTask.getType(t) + != TaskViewType.DESKTOP) + .allMatch(t -> t.getVisibleBounds().right + < centerTask.getVisibleBounds().left)); + mLauncher.assertTrue( + "DesktopTask(s) found to the left of the swiped task", + tasks.stream() + .filter(t -> t != centerTask + && OverviewTask.getType(t) + == TaskViewType.DESKTOP) + .allMatch(t -> t.getVisibleBounds().left + > centerTask.getVisibleBounds().right)); + } } } diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java index 5fd4dac084..8512d73193 100644 --- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java +++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java @@ -57,7 +57,7 @@ public final class OverviewTask { mLauncher.assertNotNull("task must not be null", task); mTask = task; mOverview = overview; - mType = getType(); + mType = getType(task); verifyActiveContainer(); } @@ -304,8 +304,12 @@ public final class OverviewTask { return containsContentDescription(expected, DEFAULT); } - private TaskViewType getType() { - String resourceName = mTask.getResourceName(); + /** + * Returns the TaskView type of the task. It will return whether the task is a single TaskView, + * a GroupedTaskView or a DesktopTaskView. + */ + static TaskViewType getType(UiObject2 task) { + String resourceName = task.getResourceName(); if (resourceName.endsWith("task_view_grouped")) { return TaskViewType.GROUPED; } else if (resourceName.endsWith("task_view_desktop")) { @@ -345,7 +349,7 @@ public final class OverviewTask { } } - private enum TaskViewType { + enum TaskViewType { SINGLE, GROUPED, DESKTOP