From 8e79419cc449229e649f36eb427d815b2532598b Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Mon, 5 Feb 2024 18:56:32 +0000 Subject: [PATCH 001/143] Revert "Intercept clicks for non-supported split targets on work..." Revert submission 25983910-disableSplitTargets Reason for revert: b/323785395 Reverted changes: /q/submissionid:25983910-disableSplitTargets (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:158cc2505f242abc11375d947d960febb7038bb2) Merged-In: I82bb808809e0be08803f3d5dd3ac779257bb64d0 Change-Id: I82bb808809e0be08803f3d5dd3ac779257bb64d0 --- .../uioverrides/QuickstepInteractionHandler.java | 5 ++++- .../launcher3/uioverrides/QuickstepLauncher.java | 14 ++------------ .../android/launcher3/views/ActivityContext.java | 13 ------------- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java index 039c0a0ad8..22f24f185a 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java @@ -28,8 +28,10 @@ import android.util.Log; import android.util.Pair; import android.view.View; import android.widget.RemoteViews; +import android.widget.Toast; import android.window.SplashScreen; +import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.ItemInfo; @@ -61,7 +63,8 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler { // Log metric StatsLogManager.StatsLogger logger = mLauncher.getStatsLogManager().logger(); logger.log(LAUNCHER_SPLIT_WIDGET_ATTEMPT); - mLauncher.handleIncorrectSplitTargetSelection(); + Toast.makeText(hostView.getContext(), R.string.split_widgets_not_supported, + Toast.LENGTH_SHORT).show(); return true; } Pair options = remoteResponse.getLaunchOptions(view); diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index ac0e53e3d2..32d10b04ef 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -36,7 +36,6 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; -import static com.android.launcher3.config.FeatureFlags.enableSplitContextually; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition; @@ -677,7 +676,7 @@ public class QuickstepLauncher extends Launcher { splitSelectSource.alreadyRunningTaskId = taskWasFound ? foundTask.key.id : INVALID_TASK_ID; - if (enableSplitContextually()) { + if (FeatureFlags.enableSplitContextually()) { startSplitToHome(splitSelectSource); } else { recentsView.initiateSplitSelect(splitSelectSource); @@ -762,7 +761,7 @@ public class QuickstepLauncher extends Launcher { super.onPause(); - if (enableSplitContextually()) { + if (FeatureFlags.enableSplitContextually()) { // If Launcher pauses before both split apps are selected, exit split screen. if (!mSplitSelectStateController.isBothSplitAppsConfirmed() && !mSplitSelectStateController.isLaunchingFirstAppFullscreen()) { @@ -1353,15 +1352,6 @@ public class QuickstepLauncher extends Launcher { return (mTaskbarUIController != null && mTaskbarUIController.hasBubbles()); } - @Override - public boolean handleIncorrectSplitTargetSelection() { - if (enableSplitContextually() && !mSplitSelectStateController.isSplitSelectActive()) { - return false; - } - mSplitSelectStateController.getSplitInstructionsView().goBoing(); - return true; - } - private static final class LauncherTaskViewController extends TaskViewTouchController { diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index 230a651698..c5317e3d5c 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -154,19 +154,6 @@ public interface ActivityContext { return false; } - /** - * Handle user tapping on unsupported target when in split selection mode. - * See {@link #isSplitSelectionActive()} - * - * @return {@code true} if this method will handle the incorrect target selection, - * {@code false} if it could not be handled or if not possible to handle based on - * current split state - */ - default boolean handleIncorrectSplitTargetSelection() { - // Overridden - return false; - } - /** * The root view to support drag-and-drop and popup support. */ From 81a7d0b1911563b3d5015a35a6e16e0925b8d413 Mon Sep 17 00:00:00 2001 From: Andreas Agvard Date: Tue, 5 Mar 2024 13:31:06 +0100 Subject: [PATCH 002/143] Adds new AssistStateManager settings Flag: NONE Bug: 326143814 Test: Unit (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d78d9bb5e2b300c68aae4c6071c913f332a994eb) Merged-In: Ie5cbae55452cf283a0ffde18e5237cebae6ee40e Change-Id: Ie5cbae55452cf283a0ffde18e5237cebae6ee40e --- .../quickstep/util/AssistStateManager.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java index f7437eb075..e9a06f712e 100644 --- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java +++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java @@ -22,6 +22,7 @@ import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.ResourceBasedOverride; import java.io.PrintWriter; +import java.util.Optional; /** Class to manage Assistant states. */ public class AssistStateManager implements ResourceBasedOverride { @@ -41,21 +42,21 @@ public class AssistStateManager implements ResourceBasedOverride { return false; } + /** Whether CsHelper CtS invocation path is available. */ + public Optional isCsHelperAvailable() { + return Optional.empty(); + } + + /** Whether VIS CtS invocation path is available. */ + public Optional isVisAvailable() { + return Optional.empty(); + } + /** Whether search recovery is available. */ public boolean isVisRecoveryEnabled() { return false; } - /** Whether search recovery is available. */ - public boolean isOseRecoveryEnabled() { - return false; - } - - /** Whether search recovery is available. */ - public boolean isOseShowSessionEnabled() { - return false; - } - /** Return {@code true} if the Settings toggle is enabled. */ public boolean isSettingsNavHandleEnabled() { return false; From 81d456f1d32d4061a3d74f264a61cb2636d92601 Mon Sep 17 00:00:00 2001 From: randypfohl Date: Thu, 7 Mar 2024 12:07:24 -0800 Subject: [PATCH 003/143] When mLastComputedTaskSize is empty we will recalculate and set it before determining scale and pivot Bug: 326550571 Test: manually set computed task size to 0 simulating unset circumstance, and ran logs verifying infinite, added fix, and verified logs showing the same scale before and after with get tasksize set Flag: none (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:fca7ee23ba35c35292e6f26ca051cd64c437ca27) Merged-In: I0f928885e2fc6cfc0d6a064d6e9f1c614bf7a5af Change-Id: I0f928885e2fc6cfc0d6a064d6e9f1c614bf7a5af --- quickstep/src/com/android/quickstep/views/RecentsView.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index ea33b4d195..c333545b1f 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -5160,6 +5160,9 @@ public abstract class RecentsView Date: Thu, 7 Mar 2024 12:39:18 -0800 Subject: [PATCH 004/143] Enable Omnient master flags in client code. Bug: 327638681 Test: Manual Flag: legacy ENABLE_LONG_PRESS_NAV_HANDLE ENABLED (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3b220c62ce97adab33d19fddc49122545d3f5989) Merged-In: Id8990ed145b4f035e5cd14e901676ebbd03733dd Change-Id: Id8990ed145b4f035e5cd14e901676ebbd03733dd --- src/com/android/launcher3/config/FeatureFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 072a96ce6e..bcdf9970bb 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -291,7 +291,7 @@ public final class FeatureFlags { "Inject fallback app corpus result when AiAi fails to return it."); public static final BooleanFlag ENABLE_LONG_PRESS_NAV_HANDLE = - getReleaseFlag(299682306, "ENABLE_LONG_PRESS_NAV_HANDLE", TEAMFOOD, + getReleaseFlag(299682306, "ENABLE_LONG_PRESS_NAV_HANDLE", ENABLED, "Enables long pressing on the bottom bar nav handle to trigger events."); public static final BooleanFlag ENABLE_SEARCH_HAPTIC_HINT = From d11b171357fb440f813c02db306be276a9ea177e Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Wed, 28 Feb 2024 21:36:07 -0800 Subject: [PATCH 005/143] Fix split selection for 3P launcher with animations off * When animations were off, the currentState in FallbackRecentsStateController is incorrect (we didn't need that check at all) * Surfaced a bug in MultiValueUpdateListener that is being fixed in ag/26416537 Test: 1P + 3P launcher all of the following: starting split from overview with animations and without rotation selecting second app before and after rotation Fixes: 327346105 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b274152194799639febe58c4fa1daa896595fd8c) Merged-In: I4f19119c30a8669bba6ced06e30773f085a78047 Change-Id: I4f19119c30a8669bba6ced06e30773f085a78047 --- .../quickstep/fallback/FallbackRecentsStateController.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 41c6f9bfb8..3e731e5f2b 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -117,9 +117,7 @@ public class FallbackRecentsStateController implements StateHandler Date: Mon, 11 Mar 2024 12:46:46 -0400 Subject: [PATCH 006/143] Disable slow recents animation handling Flag: N/A Fixes: 324228222 Test: programmatic delay and several gestures (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5b9d94adc5ca18a9dd5e7cee44dc3c0168172c8c) Merged-In: I98f3575047e442a4f57582b40cc0f36f1f113356 Change-Id: I98f3575047e442a4f57582b40cc0f36f1f113356 --- .../quickstep/TouchInteractionService.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 415f73f1aa..788012445b 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -40,7 +40,6 @@ import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_DOWN; import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_MOVE; import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_UP; -import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.RECENTS_ANIMATION_START_PENDING; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER; @@ -734,15 +733,17 @@ public class TouchInteractionService extends Service { // an ACTION_HOVER_ENTER will fire as well. boolean isHoverActionWithoutConsumer = enableCursorHoverStates() && isHoverActionWithoutConsumer(event); - if (mTaskAnimationManager.isRecentsAnimationStartPending() - && (action == ACTION_DOWN || isHoverActionWithoutConsumer)) { - ActiveGestureLog.INSTANCE.addLog( - new CompoundString("TIS.onInputEvent: ") - .append("Cannot process input event: a recents animation has been ") - .append("requested, but hasn't started."), - RECENTS_ANIMATION_START_PENDING); - return; - } + + // TODO(b/285636175): Uncomment this once WM can properly guarantee all animation callbacks +// if (mTaskAnimationManager.isRecentsAnimationStartPending() +// && (action == ACTION_DOWN || isHoverActionWithoutConsumer)) { +// ActiveGestureLog.INSTANCE.addLog( +// new CompoundString("TIS.onInputEvent: ") +// .append("Cannot process input event: a recents animation has been ") +// .append("requested, but hasn't started."), +// RECENTS_ANIMATION_START_PENDING); +// return; +// } SafeCloseable traceToken = TraceHelper.INSTANCE.allowIpcs("TIS.onInputEvent"); From 798644d1f1401a2840991b9260207b20952ff922 Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Fri, 8 Mar 2024 13:10:42 +0000 Subject: [PATCH 007/143] Fix overview live tile flickers when clicking on overview action buttons When a Live Tile is present on overview and an action is triggered (e.g., Split, Select, Screenshot), the live tile flickers due to a competing snapshot modification and animation on UI thread. The live tile is updated to switch to screenshot and at the same time the finishRecentsAnimation is triggered. This CL bumps the number of frames to wait after the view is updated to run the Runnable code. Bumping back the mDeferFrameCount to 2 solves the sync between rendering the snapshot and hiding the Live Tile. Fix: 327380570 Flag: N/A Test: Manual. Open an App -> Swipe to Overview (Live title) -> Click on Split. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:024a1018e4c96b43d8f122bb1c614c3e3ea5bab7) Merged-In: Ibd22a58580b2e5e5b866deb4e7dc87945c7e38c4 Change-Id: Ibd22a58580b2e5e5b866deb4e7dc87945c7e38c4 --- quickstep/src/com/android/quickstep/ViewUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/ViewUtils.java b/quickstep/src/com/android/quickstep/ViewUtils.java index b1320674e6..3b58dfcb39 100644 --- a/quickstep/src/com/android/quickstep/ViewUtils.java +++ b/quickstep/src/com/android/quickstep/ViewUtils.java @@ -56,7 +56,7 @@ public class ViewUtils { boolean mSurfaceCallbackRegistered = false; boolean mFinished; - int mDeferFrameCount = 1; + int mDeferFrameCount = 2; FrameHandler(View view, Runnable finishCallback, BooleanSupplier cancelled) { mViewRoot = view.getViewRootImpl(); From 514185537a2144313918ae9e7d8061331859b3e8 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Mon, 11 Mar 2024 16:53:39 -0700 Subject: [PATCH 008/143] Update Launcher state anim duration for pinned & transient taskbar * We were syncing the duration of the animation to be at most that of the taskbar/hotseat animation but only for transient taskbar. * Now we sync for transient and pinned Fixes: 328052756 Test: Anim jank doesn't repro (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:9a3c48468b35377ef46bf2b362f68c467ecd45ad) Merged-In: I21f20cbc08a2018498dde3eff871929e5a5b7d7d Change-Id: I21f20cbc08a2018498dde3eff871929e5a5b7d7d --- .../uioverrides/states/QuickstepAtomicAnimationFactory.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index 72218bf26e..8c92c7db49 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -135,8 +135,7 @@ public class QuickstepAtomicAnimationFactory extends config.duration = Math.max(config.duration, scrollDuration); // Sync scroll so that it ends before or at the same time as the taskbar animation. - if (DisplayController.isTransientTaskbar(mActivity) - && mActivity.getDeviceProfile().isTaskbarPresent) { + if (mActivity.getDeviceProfile().isTaskbarPresent) { config.duration = Math.min(config.duration, TASKBAR_TO_HOME_DURATION); } overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration)); From 0425766b1ab39d0e6e820e6a9da787a8349b04de Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Tue, 12 Mar 2024 17:48:33 +0000 Subject: [PATCH 009/143] Allow Task menu to draw down to screen bottom - Use all available spaces minus inset to draw the task menu - Also enabled scrolling for app chi1p menu Fix: 329271577 Bug: 326952853 Test: manual Flag: Nonee (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:26e487c6acd86c668518d379f90cb84f3d89a486) Merged-In: Ibdff07043f2c64495f97e11e80209bcc3f5dcb4f Change-Id: Ibdff07043f2c64495f97e11e80209bcc3f5dcb4f --- .../orientation/LandscapePagedViewHandler.java | 6 ++++++ .../orientation/PortraitPagedViewHandler.java | 6 ++++++ .../orientation/RecentsPagedOrientationHandler.java | 3 +++ .../orientation/SeascapePagedViewHandler.java | 6 ++++++ .../com/android/quickstep/views/TaskMenuView.java | 13 +++++-------- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java index 8648b56072..f345aebb0c 100644 --- a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java +++ b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java @@ -304,6 +304,12 @@ public class LandscapePagedViewHandler implements RecentsPagedOrientationHandler } } + @Override + public int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile, + float taskMenuX, float taskMenuY) { + return (int) (taskMenuX - taskInsetMargin); + } + @Override public void setTaskOptionsMenuLayoutOrientation(DeviceProfile deviceProfile, LinearLayout taskMenuLayout, int dividerSpacing, diff --git a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java index 60e6a255cb..5cd97763d1 100644 --- a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java +++ b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java @@ -209,6 +209,12 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements : thumbnailView.getMeasuredWidth()) - (2 * padding); } + @Override + public int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile, + float taskMenuX, float taskMenuY) { + return (int) (deviceProfile.availableHeightPx - taskInsetMargin - taskMenuY); + } + @Override public void setTaskOptionsMenuLayoutOrientation(DeviceProfile deviceProfile, LinearLayout taskMenuLayout, int dividerSpacing, diff --git a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java index 01c1225c40..4b65d53172 100644 --- a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java +++ b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java @@ -176,6 +176,9 @@ public interface RecentsPagedOrientationHandler extends PagedOrientationHandler View taskMenuView, float taskInsetMargin, View taskViewIcon); int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile, @StagePosition int stagePosition); + + int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile, float taskMenuX, + float taskMenuY); /** * Sets linear layout orientation for {@link com.android.launcher3.popup.SystemShortcut} items * inside task menu view. diff --git a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java index a964639e41..89c678c114 100644 --- a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java +++ b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java @@ -113,6 +113,12 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { } } + @Override + public int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile, + float taskMenuX, float taskMenuY) { + return (int) (deviceProfile.availableWidthPx - taskInsetMargin - taskMenuX); + } + @Override public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect, SplitBounds splitInfo, int desiredStagePosition) { diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java index 137455e23a..c9aad1a4d6 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java @@ -140,11 +140,9 @@ public class TaskMenuView extends AbstractFloatingView { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (!enableOverviewIconMenu()) { - int maxMenuHeight = calculateMaxHeight(); - if (MeasureSpec.getSize(heightMeasureSpec) > maxMenuHeight) { - heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxMenuHeight, MeasureSpec.AT_MOST); - } + int maxMenuHeight = calculateMaxHeight(); + if (MeasureSpec.getSize(heightMeasureSpec) > maxMenuHeight) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxMenuHeight, MeasureSpec.AT_MOST); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -416,10 +414,9 @@ public class TaskMenuView extends AbstractFloatingView { * with a margin on the top and bottom. */ private int calculateMaxHeight() { - float taskBottom = mTaskView.getHeight() + mTaskView.getPersistentTranslationY(); float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin); - - return (int) (taskBottom - taskInsetMargin - getTranslationY()); + return mTaskView.getPagedOrientationHandler().getTaskMenuHeight(taskInsetMargin, + mActivity.getDeviceProfile(), getTranslationX(), getTranslationY()); } private void setOnClosingStartCallback(Runnable onClosingStartCallback) { From 1e6bf12fdb2cefcbe173d74a3db54aa06421bc5b Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Wed, 13 Mar 2024 11:59:19 +0000 Subject: [PATCH 010/143] Set next page immediately on subsequent arrow/tab presses when navigating overivew. This allows the user to scroll as quickly as they want. Fix: 328749622 Test: manual Flag: NONE (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a9a11b47c3bff4d3ec4a4f300e12895d3235fe95) Merged-In: I493841f11407e6fb9f15fd90b5a5e55fa4ed3ad3 Change-Id: I493841f11407e6fb9f15fd90b5a5e55fa4ed3ad3 --- quickstep/src/com/android/quickstep/views/RecentsView.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index c333545b1f..1b2be4a6f6 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -4136,10 +4136,10 @@ public abstract class RecentsView Date: Wed, 13 Mar 2024 12:14:25 -0700 Subject: [PATCH 011/143] Fix bug where folder with 1 icon can exist Fix: 329357132 Flag: NONE Test: TaplDragTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5645c3ec558e2b0b6d6ae1c51dbaf93803cd51cf) Merged-In: If381ff56e051c89e9f6162f8a44f8df9e2ae5060 Change-Id: If381ff56e051c89e9f6162f8a44f8df9e2ae5060 --- src/com/android/launcher3/folder/Folder.java | 3 +++ .../android/launcher3/dragging/TaplDragTest.java | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index ec9c27dfab..ecb5c8f186 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -1039,6 +1039,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo public void onDropCompleted(final View target, final DragObject d, final boolean success) { if (success) { + if (getItemCount() <= 1) { + mDeleteFolderOnDropCompleted = true; + } if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) { replaceFolderWithFinalItem(); } diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java index d1227d8693..bf1ba39fef 100644 --- a/tests/src/com/android/launcher3/dragging/TaplDragTest.java +++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java @@ -96,6 +96,21 @@ public class TaplDragTest extends AbstractLauncherUiTest { MAPS_APP_NAME); } + /** + * Adds two icons to the Workspace and combines them into a folder, then makes sure we are able + * to remove an icon from the folder and that the folder ceases to exist since it only has one + * icon left. + */ + @Test + public void testDragOutOfFolder() { + final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1); + final HomeAppIcon photosIcon = createShortcutInCenterIfNotExist(PHOTOS_APP_NAME); + FolderIcon folderIcon = photosIcon.dragToIcon(playStoreIcon); + Folder folder = folderIcon.open(); + folder.getAppIcon(STORE_APP_NAME).internalDragToWorkspace(false, false); + assertNotNull(mLauncher.getWorkspace().tryGetWorkspaceAppIcon(STORE_APP_NAME)); + assertNotNull(mLauncher.getWorkspace().tryGetWorkspaceAppIcon(PHOTOS_APP_NAME)); + } /** Drags a shortcut from a long press menu into the workspace. * 1. Open all apps and wait for load complete. From fbda2e6ccb7f76bdf608b75b8fd218a08b9ac410 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Mon, 11 Mar 2024 20:29:01 -0400 Subject: [PATCH 012/143] Reset stashed in Taskbar All Apps for gestures instead of IME insets. Test: Manual Flag: NONE Fix: 328960039 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1956246b6e7098aeaeece3760b1ea97d096d3588) Merged-In: I62c53c21bf850b7080e12086235cba28164f4d70 Change-Id: I62c53c21bf850b7080e12086235cba28164f4d70 --- .../com/android/launcher3/taskbar/TaskbarStashController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 629c951932..3d584642b9 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -900,12 +900,12 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba } // Only update the following flags when system gesture is not in progress. + updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false); setStashedImeState(); } private void setStashedImeState() { boolean shouldStashForIme = shouldStashForIme(); - updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false); if (hasAnyFlag(FLAG_STASHED_IN_APP_IME) != shouldStashForIme) { updateStateForFlag(FLAG_STASHED_IN_APP_IME, shouldStashForIme); applyState(TASKBAR_STASH_DURATION_FOR_IME, getTaskbarStashStartDelayForIme()); From f027b4eb369d70446e8d4b82cfc320ee52f3e64d Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 18 Mar 2024 19:11:57 +0000 Subject: [PATCH 013/143] Cancel animations after reading MotionPauseDetector#isPaused() Otherwise, it clears MotionPauseDetector so isPaused returns false. Fixes: 330186943 Flag: none Test: manual (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:77802d6da48320e5f5cf5c420fe31a1aa14e478e) Merged-In: I9e0982c18cc5264a1fab53077ac551d2880a6eae Change-Id: I9e0982c18cc5264a1fab53077ac551d2880a6eae --- .../touchcontrollers/NoButtonQuickSwitchTouchController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index a92e77aa04..3a1c42dc89 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -324,7 +324,6 @@ public class NoButtonQuickSwitchTouchController implements TouchController, @Override public void onDragEnd(PointF velocity) { - cancelAnimations(); boolean horizontalFling = mSwipeDetector.isFling(velocity.x); boolean verticalFling = mSwipeDetector.isFling(velocity.y); boolean noFling = !horizontalFling && !verticalFling; @@ -353,6 +352,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, return; } InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS); + cancelAnimations(); final LauncherState targetState; if (horizontalFling && verticalFling) { From 28b28e0365448e74e9b6948a8a598e42e9495461 Mon Sep 17 00:00:00 2001 From: Andreas Agvard Date: Wed, 13 Mar 2024 18:31:51 +0100 Subject: [PATCH 014/143] Removes recovery Flag: NONE Bug: 326143814 Test: Unit (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6ce297a2ff1583e49cf3e2e1e89d1ead7f83dac0) Merged-In: Icbebeade552cb101eb4b8bae4965b4d6c972f22e Change-Id: Icbebeade552cb101eb4b8bae4965b4d6c972f22e --- .../src/com/android/quickstep/util/AssistStateManager.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java index e9a06f712e..660fc22788 100644 --- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java +++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java @@ -52,11 +52,6 @@ public class AssistStateManager implements ResourceBasedOverride { return Optional.empty(); } - /** Whether search recovery is available. */ - public boolean isVisRecoveryEnabled() { - return false; - } - /** Return {@code true} if the Settings toggle is enabled. */ public boolean isSettingsNavHandleEnabled() { return false; From b24d4d5a8f18de925b0577fa86929a9c30dfb333 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 13 Mar 2024 14:04:02 -0400 Subject: [PATCH 015/143] Update KQS task view layouts to new specs The small size of the screenshots and make text look odd. Implementing new UI specs to improve this. - Updated icon position and size - Added some blur to the thumbnail Flag: LEGACY ENABLE_KEYBOARD_QUICK_SWITCH ENABLED Fixes: 328259439 Fixes: 328692456 Test: opened KQS in dark and light mode (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dba7cbae1adfde615060598a55b5ee0edfedef9f) Merged-In: I2b20100ddeb562291edf5f0bacbce916002eee45 Change-Id: I2b20100ddeb562291edf5f0bacbce916002eee45 --- .../keyboard_quick_switch_taskview.xml | 34 ++++++----- .../layout/keyboard_quick_switch_taskview.xml | 34 ++++++----- ...board_quick_switch_taskview_thumbnail.xml} | 0 quickstep/res/values/dimens.xml | 3 +- .../taskbar/BlurredBitmapDrawable.kt | 59 +++++++++++++++++++ .../taskbar/KeyboardQuickSwitchTaskView.java | 39 +++++++----- 6 files changed, 121 insertions(+), 48 deletions(-) rename quickstep/res/layout/{keyboard_quick_switch_thumbnail.xml => keyboard_quick_switch_taskview_thumbnail.xml} (100%) create mode 100644 quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml index 69e157433a..38df75659f 100644 --- a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml +++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml @@ -36,19 +36,19 @@ app:layout_constraintEnd_toEndOf="parent"> + app:layout_constraintEnd_toStartOf="@id/thumbnail_2"/> + app:layout_constraintTop_toTopOf="@id/thumbnail_1" + app:layout_constraintBottom_toBottomOf="@id/thumbnail_1" + app:layout_constraintStart_toStartOf="@id/thumbnail_1" + app:layout_constraintEnd_toEndOf="@id/thumbnail_1"/> + app:layout_constraintTop_toTopOf="@id/thumbnail_2" + app:layout_constraintBottom_toBottomOf="@id/thumbnail_2" + app:layout_constraintStart_toStartOf="@id/thumbnail_2" + app:layout_constraintEnd_toEndOf="@id/thumbnail_2"/> diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview.xml b/quickstep/res/layout/keyboard_quick_switch_taskview.xml index 6ed3c6ede5..c0ace9a1ae 100644 --- a/quickstep/res/layout/keyboard_quick_switch_taskview.xml +++ b/quickstep/res/layout/keyboard_quick_switch_taskview.xml @@ -36,51 +36,53 @@ app:layout_constraintEnd_toEndOf="parent"> + app:layout_constraintTop_toTopOf="@id/thumbnail_1" + app:layout_constraintBottom_toBottomOf="@id/thumbnail_1" + app:layout_constraintStart_toStartOf="@id/thumbnail_1" + app:layout_constraintEnd_toEndOf="@id/thumbnail_1"/> + app:layout_constraintTop_toTopOf="@id/thumbnail_2" + app:layout_constraintBottom_toBottomOf="@id/thumbnail_2" + app:layout_constraintStart_toStartOf="@id/thumbnail_2" + app:layout_constraintEnd_toEndOf="@id/thumbnail_2"/> diff --git a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml b/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml similarity index 100% rename from quickstep/res/layout/keyboard_quick_switch_thumbnail.xml rename to quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 33313218a6..f90d96f3f5 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -439,8 +439,7 @@ 4dp 104dp 134dp - 28dp - 4dp + 52dp 20dp 56dp 16dp diff --git a/quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt b/quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt new file mode 100644 index 0000000000..8aee1aada2 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt @@ -0,0 +1,59 @@ +/* + * 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.taskbar + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.PixelFormat +import android.graphics.RenderEffect +import android.graphics.RenderNode +import android.graphics.Shader +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.DrawableWrapper + +/* BitmapDrawable that can blur the given bitmap. */ +class BlurredBitmapDrawable(bitmap: Bitmap?, radiusX: Float, radiusY: Float) : + DrawableWrapper(BitmapDrawable(bitmap)) { + private val mBlurRenderNode: RenderNode = RenderNode("BlurredConstraintLayoutBlurNode") + + constructor(bitmap: Bitmap?, radius: Float) : this(bitmap, radius, radius) + + init { + mBlurRenderNode.setRenderEffect( + RenderEffect.createBlurEffect(radiusX, radiusY, Shader.TileMode.CLAMP) + ) + } + + override fun draw(canvas: Canvas) { + if (!canvas.isHardwareAccelerated) { + super.draw(canvas) + return + } + mBlurRenderNode.setPosition(bounds) + if (!mBlurRenderNode.hasDisplayList()) { + // Record render node if its display list is not recorded or discarded + // (which happens when it's no longer drawn by anything). + val recordingCanvas = mBlurRenderNode.beginRecording() + super.draw(recordingCanvas) + mBlurRenderNode.endRecording() + } + canvas.drawRenderNode(mBlurRenderNode) + } + + override fun getOpacity(): Int { + return PixelFormat.OPAQUE + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java index a9d50b9332..5b407f0b5d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java +++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java @@ -23,6 +23,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; @@ -47,6 +48,8 @@ import kotlin.Unit; */ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { + private static final float THUMBNAIL_BLUR_RADIUS = 1f; + @ColorInt private final int mBorderColor; @Nullable private BorderAnimator mBorderAnimator; @@ -89,10 +92,10 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); - mThumbnailView1 = findViewById(R.id.thumbnail1); - mThumbnailView2 = findViewById(R.id.thumbnail2); - mIcon1 = findViewById(R.id.icon1); - mIcon2 = findViewById(R.id.icon2); + mThumbnailView1 = findViewById(R.id.thumbnail_1); + mThumbnailView2 = findViewById(R.id.thumbnail_2); + mIcon1 = findViewById(R.id.icon_1); + mIcon2 = findViewById(R.id.icon_2); mContent = findViewById(R.id.content); Resources resources = mContext.getResources(); @@ -167,10 +170,7 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { @Nullable ImageView thumbnailView, @Nullable Task task, @Nullable ThumbnailUpdateFunction updateFunction) { - if (thumbnailView == null) { - return; - } - if (task == null) { + if (thumbnailView == null || task == null) { return; } if (updateFunction == null) { @@ -182,19 +182,30 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout { } private void applyThumbnail( - @NonNull ImageView thumbnailView, ThumbnailData thumbnailData) { + @NonNull ImageView thumbnailView, + ThumbnailData thumbnailData) { Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail; - thumbnailView.setVisibility(VISIBLE); - thumbnailView.setImageBitmap(bm); + if (thumbnailView.getVisibility() != VISIBLE) { + thumbnailView.setVisibility(VISIBLE); + } + thumbnailView.setImageDrawable(new BlurredBitmapDrawable(bm, THUMBNAIL_BLUR_RADIUS)); } private void applyIcon(@Nullable ImageView iconView, @Nullable Task task) { - if (iconView == null || task == null) { + if (iconView == null || task == null || task.icon == null) { return; } - iconView.setVisibility(VISIBLE); - iconView.setImageDrawable(task.icon); + Drawable.ConstantState constantState = task.icon.getConstantState(); + if (constantState == null) { + return; + } + if (iconView.getVisibility() != VISIBLE) { + iconView.setVisibility(VISIBLE); + } + // Use the bitmap directly since the drawable's scale can change + iconView.setImageDrawable( + constantState.newDrawable(getResources(), getContext().getTheme())); } protected interface ThumbnailUpdateFunction { From 00bd00fd4e97cc36a12d58283a3e6fea3d5e76ca Mon Sep 17 00:00:00 2001 From: Brandon Dayauon Date: Thu, 7 Mar 2024 10:14:44 -0800 Subject: [PATCH 016/143] Disable two line text legacy flag. Will now repurpose the twolinetoggle flag to be the flag that will make twoline text enabled/disabled. bug: 316027081 Test: presubmit manually: https://screenshot.googleplex.com/BsZGCm7DrTZLwG4 Flag: com.android.launcher3.enable_twoline_toggle Staging (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:68c18236adb5d49d5ba3c5a19187759af63a53b4) Merged-In: Idef427bad6551ae56b13e35393e076b8e000af5a Change-Id: Idef427bad6551ae56b13e35393e076b8e000af5a --- .../appprediction/PredictionRowView.java | 6 +- src/com/android/launcher3/BubbleTextView.java | 11 +- src/com/android/launcher3/DeviceProfile.java | 5 +- .../launcher3/allapps/BaseAllAppsAdapter.java | 7 +- .../launcher3/config/FeatureFlags.java | 7 +- .../launcher3/AbstractDeviceProfileTest.kt | 13 +- .../launcher3/ui/BubbleTextViewTest.java | 295 ++++++++---------- 7 files changed, 147 insertions(+), 197 deletions(-) diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java index e1443d0987..b36fd662fe 100644 --- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -138,9 +138,9 @@ public class PredictionRowView int totalHeight = iconHeight + iconPadding + textHeight + mVerticalPadding * 2; // Prediction row height will be 4dp bigger than the regular apps in A-Z list when two line // is not enabled. Otherwise, the extra height will increase by just the textHeight. - int extraHeight = (FeatureFlags.enableTwolineAllapps() && (!Flags.enableTwolineToggle() - || (Flags.enableTwolineToggle() && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get( - getContext())))) ? textHeight : mTopRowExtraHeight; + int extraHeight = (Flags.enableTwolineToggle() && + LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get(getContext())) + ? textHeight : mTopRowExtraHeight; totalHeight += extraHeight; return getVisibility() == GONE ? 0 : totalHeight + getPaddingTop() + getPaddingBottom(); } diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 4f071fe500..3ae1ce117b 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -285,9 +285,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, mDotParams.scale = 0f; mForceHideDot = false; setBackground(null); - if (FeatureFlags.enableTwolineAllapps() || FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()) { - setMaxLines(1); - } setTag(null); if (mIconLoadRequest != null) { @@ -299,6 +296,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, setAlpha(1); setScaleY(1); setTranslationY(0); + setMaxLines(1); setVisibility(VISIBLE); } @@ -428,10 +426,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, * Only if actual text can be displayed in two line, the {@code true} value will be effective. */ protected boolean shouldUseTwoLine() { - return FeatureFlags.enableTwolineAllapps() && isCurrentLanguageEnglish() - && (mDisplay == DISPLAY_ALL_APPS || mDisplay == DISPLAY_PREDICTION_ROW) - && (!Flags.enableTwolineToggle() || (Flags.enableTwolineToggle() - && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get(getContext()))); + return isCurrentLanguageEnglish() && (mDisplay == DISPLAY_ALL_APPS + || mDisplay == DISPLAY_PREDICTION_ROW) && (Flags.enableTwolineToggle() + && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get(getContext())); } protected boolean isCurrentLanguageEnglish() { diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 4b4bdc2ecf..f96d59ebba 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -1233,9 +1233,8 @@ public class DeviceProfile { if (isVerticalLayout && !mIsResponsiveGrid) { hideWorkspaceLabelsIfNotEnoughSpace(); } - if (FeatureFlags.enableTwolineAllapps() - && (!Flags.enableTwolineToggle() || (Flags.enableTwolineToggle() - && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get(context)))) { + if ((Flags.enableTwolineToggle() + && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get(context))) { // Add extra textHeight to the existing allAppsCellHeight. allAppsCellHeightPx += Utilities.calculateTextHeight(allAppsIconTextSizePx); } diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java index ca587c16f0..5e5795d4e1 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java @@ -223,10 +223,9 @@ public abstract class BaseAllAppsAdapter ex public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case VIEW_TYPE_ICON: - int layout = (FeatureFlags.enableTwolineAllapps() && - (!Flags.enableTwolineToggle() || (Flags.enableTwolineToggle() - && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get( - mActivityContext.getApplicationContext())))) + int layout = (Flags.enableTwolineToggle() + && LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE.get( + mActivityContext.getApplicationContext())) ? R.layout.all_apps_icon_twoline : R.layout.all_apps_icon; BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate( layout, parent, false); diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index bcdf9970bb..262b2a1e43 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -158,7 +158,7 @@ public final class FeatureFlags { // TODO(Block 5): Clean up flags public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851, - "ENABLE_TWOLINE_DEVICESEARCH", ENABLED, + "ENABLE_TWOLINE_DEVICESEARCH", DISABLED, "Enable two line label for icons with labels on device search."); public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143, @@ -274,10 +274,7 @@ public final class FeatureFlags { // Aconfig migration complete for ENABLE_TWOLINE_ALLAPPS. public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937, - "ENABLE_TWOLINE_ALLAPPS", ENABLED, "Enables two line label inside all apps."); - public static boolean enableTwolineAllapps() { - return ENABLE_TWOLINE_ALLAPPS.get() || Flags.enableTwolineAllapps(); - } + "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps."); public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693, "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps"); diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index 3ba563d0df..ffcf83f303 100644 --- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -38,17 +38,17 @@ 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.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 @@ -274,7 +274,8 @@ abstract class AbstractDeviceProfileTest { isGestureMode: Boolean = true, densityDpi: Int ) { - setFlagsRule.setFlags(false, Flags.FLAG_ENABLE_TWOLINE_TOGGLE) + setFlagsRule.setFlags(true, Flags.FLAG_ENABLE_TWOLINE_TOGGLE) + LauncherPrefs.get(testContext).put(LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE, true) val windowsBounds = perDisplayBoundsCache[displayInfo]!! val realBounds = windowsBounds[rotation] whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo) diff --git a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java index 6df3ecd078..90ded100fe 100644 --- a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java +++ b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java @@ -22,7 +22,7 @@ import static com.android.launcher3.BubbleTextView.DISPLAY_ALL_APPS; import static com.android.launcher3.BubbleTextView.DISPLAY_PREDICTION_ROW; import static com.android.launcher3.BubbleTextView.DISPLAY_SEARCH_RESULT; import static com.android.launcher3.BubbleTextView.DISPLAY_SEARCH_RESULT_SMALL; -import static com.android.launcher3.config.FeatureFlags.ENABLE_TWOLINE_ALLAPPS; +import static com.android.launcher3.LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE; import static com.google.common.truth.Truth.assertThat; @@ -39,6 +39,7 @@ import android.view.ViewGroup; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Flags; +import com.android.launcher3.LauncherPrefs; import com.android.launcher3.Utilities; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; @@ -46,7 +47,6 @@ import com.android.launcher3.search.StringMatcherUtility; import com.android.launcher3.util.ActivityContextWrapper; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.IntArray; -import com.android.launcher3.util.TestUtil; import com.android.launcher3.views.BaseDragLayer; import org.junit.Before; @@ -96,13 +96,14 @@ public class BubbleTextViewTest { private Context mContext; private int mLimitedWidth; private AppInfo mGmailAppInfo; + private LauncherPrefs mLauncherPrefs; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); Utilities.enableRunningInTestHarnessForTests(); - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); mContext = new ActivityContextWrapper(getApplicationContext()); + mLauncherPrefs = LauncherPrefs.get(mContext); mBubbleTextView = new BubbleTextView(mContext); mBubbleTextView.reset(); @@ -130,190 +131,155 @@ public class BubbleTextViewTest { @Test public void testEmptyString_flagOn() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - mItemInfoWithIcon.title = EMPTY_STRING; - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + mItemInfoWithIcon.title = EMPTY_STRING; + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertNotEquals(TWO_LINE, mBubbleTextView.getMaxLines()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertNotEquals(TWO_LINE, mBubbleTextView.getMaxLines()); } @Test public void testEmptyString_flagOff() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) { - mItemInfoWithIcon.title = EMPTY_STRING; - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mItemInfoWithIcon.title = EMPTY_STRING; + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test public void testStringWithSpaceLongerThanCharLimit_flagOn() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "Battery Stats" - mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "Battery Stats" + mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); } @Test public void testStringWithSpaceLongerThanCharLimit_flagOff() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) { - // test string: "Battery Stats" - mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + // test string: "Battery Stats" + mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test public void testLongStringNoSpaceLongerThanCharLimit_flagOn() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "flutterappflorafy" - mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "flutterappflorafy" + mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test public void testLongStringNoSpaceLongerThanCharLimit_flagOff() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) { - // test string: "flutterappflorafy" - mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + // test string: "flutterappflorafy" + mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test public void testLongStringWithSpaceLongerThanCharLimit_flagOn() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "System UWB Field Test" - mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "System UWB Field Test" + mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); } @Test public void testLongStringWithSpaceLongerThanCharLimit_flagOff() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) { - // test string: "System UWB Field Test" - mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + // test string: "System UWB Field Test" + mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test public void testLongStringSymbolLongerThanCharLimit_flagOn() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "LEGO®Builder" - mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "LEGO®Builder" + mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); } @Test public void testLongStringSymbolLongerThanCharLimit_flagOff() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) { - // test string: "LEGO®Builder" - mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + // test string: "LEGO®Builder" + mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test @@ -374,58 +340,49 @@ public class BubbleTextViewTest { @Test public void testEnsurePredictionRowIsTwoLine() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "Battery Stats" - mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW); - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "Battery Stats" + mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW); + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); } @Test public void modifyTitleToSupportMultiLine_whenLimitedHeight_shouldBeOneLine() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "LEGO®Builder" - mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "LEGO®Builder" + mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, LIMITED_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(ONE_LINE, mBubbleTextView.getLineCount()); } @Test public void modifyTitleToSupportMultiLine_whenUnlimitedHeight_shouldBeTwoLine() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_ALLAPPS); - try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) { - // test string: "LEGO®Builder" - mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; - mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); - mBubbleTextView.applyLabel(mItemInfoWithIcon); - mBubbleTextView.setTypeface(Typeface.MONOSPACE); - mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TWOLINE_TOGGLE); + mLauncherPrefs.put(ENABLE_TWOLINE_ALLAPPS_TOGGLE, true); + // test string: "LEGO®Builder" + mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT; + mBubbleTextView.setDisplay(DISPLAY_ALL_APPS); + mBubbleTextView.applyLabel(mItemInfoWithIcon); + mBubbleTextView.setTypeface(Typeface.MONOSPACE); + mBubbleTextView.measure(mLimitedWidth, MAX_HEIGHT); - mBubbleTextView.onPreDraw(); + mBubbleTextView.onPreDraw(); - assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); - } catch (Exception e) { - throw new RuntimeException(e); - } + assertEquals(TWO_LINE, mBubbleTextView.getLineCount()); } @Test From 2bac10b2372155cc64adafa5cfa76ecdb94c2da6 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Thu, 21 Mar 2024 11:30:39 +0800 Subject: [PATCH 017/143] Do not report finish in mergeAnimation... ...if the handler don't know how to process the transition. So the Transitions can pass that transition to next handler. Flag: NONE Bug: 328619216 Test: manual, use alt+tab to relaunch a task where it's activity is destroyed. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7130116894eb7f756a16da6b5ff0e754a356d50d) Merged-In: Idf3f78103a56e91806ec2f6e364c6e8e7f4e205c Change-Id: Idf3f78103a56e91806ec2f6e364c6e8e7f4e205c --- .../taskbar/KeyboardQuickSwitchViewController.java | 3 ++- .../com/android/quickstep/util/SlideInRemoteTransition.kt | 7 +------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java index c830aa8640..701edd000b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java @@ -151,7 +151,8 @@ public class KeyboardQuickSwitchViewController { context.getDeviceProfile().overviewPageSpacing, QuickStepContract.getWindowCornerRadius(context), AnimationUtils.loadInterpolator( - context, android.R.interpolator.fast_out_extra_slow_in))); + context, android.R.interpolator.fast_out_extra_slow_in)), + "SlideInTransition"); if (mOnDesktop) { UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext()) diff --git a/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt b/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt index 9f7b46d90f..134729163e 100644 --- a/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt +++ b/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt @@ -46,12 +46,7 @@ class SlideInRemoteTransition( mergeTarget: IBinder, finishCB: IRemoteTransitionFinishedCallback ) { - - try { - finishCB.onTransitionFinished(null, Transaction()) - } catch (e: RemoteException) { - // Ignore - } + // Do not report finish if we don't know how to handle this transition. } override fun startAnimation( From ed9b5e0a5a6c2f2437daa67393a9648441fbb76a Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 13 Mar 2024 16:19:21 -0400 Subject: [PATCH 018/143] Close the KQS view when touching the gesture nav region Also, stop handling KQS open/close during gestures Flag: LEGACY ENABLE_KEYBOARD_QUICK_SWITCH ENABLED Fixes: 328689890 Fixes: 328689534 Fixes: 328692760 Test: attempted gestures while KQS is shown. attempted KQS while attempting gestures (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:14d912b062e69fe8bc4729b6f8b40e53d5b4a669) Merged-In: Idbd1f9cef09d9fbf611350d0847d94ccf8300369 Change-Id: Idbd1f9cef09d9fbf611350d0847d94ccf8300369 --- .../KeyboardQuickSwitchController.java | 6 ++- .../taskbar/TaskbarActivityContext.java | 5 +++ .../quickstep/OverviewCommandHelper.java | 8 ++++ .../quickstep/TouchInteractionService.java | 4 ++ .../android/quickstep/views/RecentsView.java | 45 ++++++++++--------- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java index f15d12b12d..8566e20e14 100644 --- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java +++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java @@ -193,10 +193,14 @@ public final class KeyboardQuickSwitchController implements } void closeQuickSwitchView() { + closeQuickSwitchView(true); + } + + void closeQuickSwitchView(boolean animate) { if (mQuickSwitchViewController == null) { return; } - mQuickSwitchViewController.closeQuickSwitchView(true); + mQuickSwitchViewController.closeQuickSwitchView(animate); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 87662e6c1a..ecaf89aa58 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -1554,4 +1554,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { public float getStashedTaskbarScale() { return mControllers.stashedHandleViewController.getStashedHandleHintScale().value; } + + /** Closes the KeyboardQuickSwitchView without an animation if open. */ + public void closeKeyboardQuickSwitchView() { + mControllers.keyboardQuickSwitchController.closeQuickSwitchView(false); + } } diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 65b5397fd1..56c9a00016 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -248,7 +248,15 @@ public class OverviewCommandHelper { case TYPE_SHOW: // already visible return true; + case TYPE_KEYBOARD_INPUT: { + if (visibleRecentsView.isHandlingTouch()) { + return true; + } + } case TYPE_HIDE: { + if (visibleRecentsView.isHandlingTouch()) { + return true; + } mKeyboardTaskFocusIndex = INVALID_PAGE; int currentPage = visibleRecentsView.getNextPage(); TaskView tv = (currentPage >= 0 diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 788012445b..719c4f7f70 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -754,6 +754,10 @@ public class TouchInteractionService extends Service { boolean isOneHandedModeActive = mDeviceState.isOneHandedModeActive(); boolean isInSwipeUpTouchRegion = mRotationTouchHelper.isInSwipeUpTouchRegion(event); + TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext(); + if (isInSwipeUpTouchRegion && tac != null) { + tac.closeKeyboardQuickSwitchView(); + } if ((!isOneHandedModeActive && isInSwipeUpTouchRegion) || isHoverActionWithoutConsumer) { reasonString.append(!isOneHandedModeActive && isInSwipeUpTouchRegion diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 1b2be4a6f6..e516870de2 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -4220,30 +4220,31 @@ public abstract class RecentsView Date: Thu, 14 Mar 2024 19:12:50 -0400 Subject: [PATCH 019/143] Support toggling Taskbar All Apps with 3P Launcher. Taskbar All Apps exists regardless of the default launcher. Thus, we can toggle it on large screen devices. This CL ties registering the system action to default launcher and taskbar's enablement. Test: adb shell input keyevent 117 Test: AllAppsActionManagerTest Flag: LEGACY ENABLE_ALL_APPS_SEARCH_IN_TASKBAR ENABLED Fix: 317259709 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c113b277e61eb0391f050d6c12bf36711d727733) Merged-In: I26f0ed9e921beac762f3f9e6aaceb1002ad4801a Change-Id: I26f0ed9e921beac762f3f9e6aaceb1002ad4801a --- .../taskbar/LauncherTaskbarUIController.java | 7 ++ .../taskbar/TaskbarActivityContext.java | 4 + .../launcher3/taskbar/TaskbarManager.java | 36 ++++---- .../taskbar/TaskbarUIController.java | 5 + .../android/quickstep/AllAppsActionManager.kt | 90 ++++++++++++++++++ .../quickstep/TouchInteractionService.java | 38 ++------ .../quickstep/AllAppsActionManagerTest.kt | 91 +++++++++++++++++++ 7 files changed, 224 insertions(+), 47 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/AllAppsActionManager.kt create mode 100644 quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 1e861d2fb5..30be0580ec 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -413,6 +413,13 @@ public class LauncherTaskbarUIController extends TaskbarUIController { return mTaskbarLauncherStateController.isInOverview(); } + @Override + protected boolean canToggleHomeAllApps() { + return mLauncher.isResumed() + && !mTaskbarLauncherStateController.isInOverview() + && !mLauncher.areFreeformTasksVisible(); + } + @Override public RecentsView getRecentsView() { return mLauncher.getOverviewPanel(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index ecaf89aa58..cb8cd3763b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -1559,4 +1559,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { public void closeKeyboardQuickSwitchView() { mControllers.keyboardQuickSwitchController.closeQuickSwitchView(false); } + + boolean canToggleHomeAllApps() { + return mControllers.uiController.canToggleHomeAllApps(); + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index ff33ca9779..ecbc7e7fdc 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -23,7 +23,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static com.android.launcher3.BaseActivity.EVENT_DESTROYED; import static com.android.launcher3.Flags.enableUnfoldStateAnimation; -import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION; import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate; import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY; @@ -69,6 +68,7 @@ import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.SettingsCache; import com.android.launcher3.util.SimpleBroadcastReceiver; +import com.android.quickstep.AllAppsActionManager; import com.android.quickstep.RecentsActivity; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TouchInteractionService; @@ -158,6 +158,8 @@ public class TaskbarManager { private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver = new SimpleBroadcastReceiver(this::showTaskbarFromBroadcast); + private final AllAppsActionManager mAllAppsActionManager; + private final Runnable mActivityOnDestroyCallback = new Runnable() { @Override public void run() { @@ -212,12 +214,14 @@ public class TaskbarManager { private Boolean mFolded; @SuppressLint("WrongConstant") - public TaskbarManager(TouchInteractionService service) { + public TaskbarManager( + TouchInteractionService service, AllAppsActionManager allAppsActionManager) { Display display = service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY); mContext = service.createWindowContext(display, ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL, null); + mAllAppsActionManager = allAppsActionManager; mNavigationBarPanelContext = ENABLE_TASKBAR_NAVBAR_UNIFICATION ? service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null) : null; @@ -291,10 +295,10 @@ public class TaskbarManager { recreateTaskbar(); } else { // Config change might be handled without re-creating the taskbar - if (dp != null && !isTaskbarPresent(dp)) { + if (dp != null && !isTaskbarEnabled(dp)) { destroyExistingTaskbar(); } else { - if (dp != null && isTaskbarPresent(dp)) { + if (dp != null && isTaskbarEnabled(dp)) { if (ENABLE_TASKBAR_NAVBAR_UNIFICATION) { // Re-initialize for screen size change? Should this be done // by looking at screen-size change flag in configDiff in the @@ -349,7 +353,7 @@ public class TaskbarManager { } DeviceProfile dp = mUserUnlocked ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null; - if (dp == null || !isTaskbarPresent(dp)) { + if (dp == null || !isTaskbarEnabled(dp)) { removeTaskbarRootViewFromWindow(); } } @@ -369,20 +373,11 @@ public class TaskbarManager { * @param homeAllAppsIntent Intent used if Taskbar is not enabled or Launcher is resumed. */ public void toggleAllApps(Intent homeAllAppsIntent) { - if (mTaskbarActivityContext == null) { + if (mTaskbarActivityContext == null || mTaskbarActivityContext.canToggleHomeAllApps()) { mContext.startActivity(homeAllAppsIntent); - return; + } else { + mTaskbarActivityContext.toggleAllAppsSearch(); } - - if (mActivity != null - && mActivity.isResumed() - && !mActivity.isInState(OVERVIEW) - && !(mActivity instanceof QuickstepLauncher l && l.areFreeformTasksVisible())) { - mContext.startActivity(homeAllAppsIntent); - return; - } - - mTaskbarActivityContext.toggleAllAppsSearch(); } /** @@ -477,9 +472,12 @@ public class TaskbarManager { DeviceProfile dp = mUserUnlocked ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null; + // All Apps action is unrelated to navbar unification, so we only need to check DP. + mAllAppsActionManager.setTaskbarPresent(dp != null && dp.isTaskbarPresent); + destroyExistingTaskbar(); - boolean isTaskbarEnabled = dp != null && isTaskbarPresent(dp); + boolean isTaskbarEnabled = dp != null && isTaskbarEnabled(dp); debugWhyTaskbarNotDestroyed("recreateTaskbar: isTaskbarEnabled=" + isTaskbarEnabled + " [dp != null (i.e. mUserUnlocked)]=" + (dp != null) + " FLAG_HIDE_NAVBAR_WINDOW=" + ENABLE_TASKBAR_NAVBAR_UNIFICATION @@ -544,7 +542,7 @@ public class TaskbarManager { } } - private static boolean isTaskbarPresent(DeviceProfile deviceProfile) { + private static boolean isTaskbarEnabled(DeviceProfile deviceProfile) { return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index efe1e39f97..109400ee6b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -197,6 +197,11 @@ public class TaskbarUIController { return false; } + /** Returns {@code true} if Home All Apps available instead of Taskbar All Apps. */ + protected boolean canToggleHomeAllApps() { + return false; + } + @CallSuper protected void dumpLogs(String prefix, PrintWriter pw) { pw.println(String.format( diff --git a/quickstep/src/com/android/quickstep/AllAppsActionManager.kt b/quickstep/src/com/android/quickstep/AllAppsActionManager.kt new file mode 100644 index 0000000000..fd2ed3ac18 --- /dev/null +++ b/quickstep/src/com/android/quickstep/AllAppsActionManager.kt @@ -0,0 +1,90 @@ +/* + * 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.quickstep + +import android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS +import android.app.PendingIntent +import android.app.RemoteAction +import android.content.Context +import android.graphics.drawable.Icon +import android.view.accessibility.AccessibilityManager +import com.android.launcher3.R +import java.util.concurrent.Executor + +/** + * Registers a [RemoteAction] for toggling All Apps if needed. + * + * We need this action when either [isHomeAndOverviewSame] or [isTaskbarPresent] is `true`. When + * home and overview are the same, we can control Launcher's or Taskbar's All Apps tray. If they are + * not the same, but Taskbar is present, we can only control Taskbar's tray. + */ +class AllAppsActionManager( + private val context: Context, + private val bgExecutor: Executor, + private val createAllAppsPendingIntent: () -> PendingIntent, +) { + + /** `true` if home and overview are the same Activity. */ + var isHomeAndOverviewSame = false + set(value) { + field = value + updateSystemAction() + } + + /** `true` if Taskbar is enabled. */ + var isTaskbarPresent = false + set(value) { + field = value + updateSystemAction() + } + + /** `true` if the action should be registered. */ + var isActionRegistered = false + private set + + private fun updateSystemAction() { + val shouldRegisterAction = isHomeAndOverviewSame || isTaskbarPresent + if (isActionRegistered == shouldRegisterAction) return + isActionRegistered = shouldRegisterAction + + bgExecutor.execute { + val accessibilityManager = + context.getSystemService(AccessibilityManager::class.java) ?: return@execute + if (shouldRegisterAction) { + accessibilityManager.registerSystemAction( + RemoteAction( + Icon.createWithResource(context, R.drawable.ic_apps), + context.getString(R.string.all_apps_label), + context.getString(R.string.all_apps_label), + createAllAppsPendingIntent(), + ), + GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS, + ) + } else { + accessibilityManager.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS) + } + } + } + + fun onDestroy() { + context + .getSystemService(AccessibilityManager::class.java) + ?.unregisterSystemAction( + GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS, + ) + } +} diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 719c4f7f70..b43c5201ce 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -31,6 +31,7 @@ import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent; import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe; import static com.android.launcher3.config.FeatureFlags.ENABLE_TRACKPAD_GESTURE; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; +import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN; import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH; import static com.android.quickstep.GestureState.DEFAULT_STATE; @@ -59,14 +60,12 @@ import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SP import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW; import android.app.PendingIntent; -import android.app.RemoteAction; import android.app.Service; import android.content.IIntentReceiver; import android.content.IIntentSender; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Region; -import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; @@ -77,7 +76,6 @@ import android.view.Choreographer; import android.view.InputDevice; import android.view.InputEvent; import android.view.MotionEvent; -import android.view.accessibility.AccessibilityManager; import androidx.annotation.BinderThread; import androidx.annotation.NonNull; @@ -88,7 +86,6 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.ConstantItem; import com.android.launcher3.EncryptionType; import com.android.launcher3.LauncherPrefs; -import com.android.launcher3.R; import com.android.launcher3.anim.AnimatedFloat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.provider.RestoreDbTask; @@ -101,7 +98,6 @@ import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.uioverrides.flags.FlagsFactory; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.util.DisplayController; -import com.android.launcher3.util.Executors; import com.android.launcher3.util.LockedUserState; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.util.ScreenOnTracker; @@ -488,6 +484,7 @@ public class TouchInteractionService extends Service { private TaskbarManager mTaskbarManager; private Function mSwipeUpProxyProvider = i -> null; + private AllAppsActionManager mAllAppsActionManager; @Override public void onCreate() { @@ -497,7 +494,9 @@ public class TouchInteractionService extends Service { mMainChoreographer = Choreographer.getInstance(); mAM = ActivityManagerWrapper.getInstance(); mDeviceState = new RecentsAnimationDeviceState(this, true); - mTaskbarManager = new TaskbarManager(this); + mAllAppsActionManager = new AllAppsActionManager( + this, UI_HELPER_EXECUTOR, this::createAllAppsPendingIntent); + mTaskbarManager = new TaskbarManager(this, mAllAppsActionManager); mRotationTouchHelper = mDeviceState.getRotationTouchHelper(); mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); BootAwarePreloader.start(this); @@ -590,16 +589,7 @@ public class TouchInteractionService extends Service { } private void onOverviewTargetChange(boolean isHomeAndOverviewSame) { - Executors.UI_HELPER_EXECUTOR.execute(() -> { - AccessibilityManager am = getSystemService(AccessibilityManager.class); - - if (isHomeAndOverviewSame) { - am.registerSystemAction( - createAllAppsAction(), GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS); - } else { - am.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS); - } - }); + mAllAppsActionManager.setHomeAndOverviewSame(isHomeAndOverviewSame); StatefulActivity newOverviewActivity = mOverviewComponentObserver.getActivityInterface() .getCreatedActivity(); @@ -609,13 +599,12 @@ public class TouchInteractionService extends Service { mTISBinder.onOverviewTargetChange(); } - private RemoteAction createAllAppsAction() { + private PendingIntent createAllAppsPendingIntent() { final Intent homeIntent = new Intent(mOverviewComponentObserver.getHomeIntent()) .setAction(INTENT_ACTION_ALL_APPS_TOGGLE); - final PendingIntent actionPendingIntent; if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { - actionPendingIntent = new PendingIntent(new IIntentSender.Stub() { + return new PendingIntent(new IIntentSender.Stub() { @Override public void send(int code, Intent intent, String resolvedType, IBinder allowlistToken, IIntentReceiver finishedReceiver, @@ -624,18 +613,12 @@ public class TouchInteractionService extends Service { } }); } else { - actionPendingIntent = PendingIntent.getActivity( + return PendingIntent.getActivity( this, GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS, homeIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } - - return new RemoteAction( - Icon.createWithResource(this, R.drawable.ic_apps), - getString(R.string.all_apps_label), - getString(R.string.all_apps_label), - actionPendingIntent); } @UiThread @@ -678,8 +661,7 @@ public class TouchInteractionService extends Service { mDeviceState.destroy(); SystemUiProxy.INSTANCE.get(this).clearProxy(); - getSystemService(AccessibilityManager.class) - .unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS); + mAllAppsActionManager.onDestroy(); mTaskbarManager.destroy(); sConnected = false; diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt new file mode 100644 index 0000000000..73b35e8a5c --- /dev/null +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt @@ -0,0 +1,91 @@ +/* + * 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.quickstep + +import android.app.PendingIntent +import android.content.IIntentSender +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR +import com.android.launcher3.util.TestUtil +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.Semaphore +import java.util.concurrent.TimeUnit.SECONDS +import org.junit.Test +import org.junit.runner.RunWith + +private const val TIMEOUT = 5L + +@RunWith(AndroidJUnit4::class) +class AllAppsActionManagerTest { + private val callbackSemaphore = Semaphore(0) + private val bgExecutor = UI_HELPER_EXECUTOR + + private val allAppsActionManager = + AllAppsActionManager( + InstrumentationRegistry.getInstrumentation().targetContext, + bgExecutor, + ) { + callbackSemaphore.release() + PendingIntent(IIntentSender.Default()) + } + + @Test + fun taskbarPresent_actionRegistered() { + allAppsActionManager.isTaskbarPresent = true + assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue() + assertThat(allAppsActionManager.isActionRegistered).isTrue() + } + + @Test + fun homeAndOverviewSame_actionRegistered() { + allAppsActionManager.isHomeAndOverviewSame = true + assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue() + assertThat(allAppsActionManager.isActionRegistered).isTrue() + } + + @Test + fun toggleTaskbar_destroyedAfterActionRegistered_actionUnregistered() { + allAppsActionManager.isTaskbarPresent = true + assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue() + + allAppsActionManager.isTaskbarPresent = false + TestUtil.runOnExecutorSync(bgExecutor) {} // Force system action to unregister. + assertThat(allAppsActionManager.isActionRegistered).isFalse() + } + + @Test + fun toggleTaskbar_destroyedBeforeActionRegistered_pendingActionUnregistered() { + allAppsActionManager.isTaskbarPresent = true + allAppsActionManager.isTaskbarPresent = false + + TestUtil.runOnExecutorSync(bgExecutor) {} // Force system action to unregister. + assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue() + assertThat(allAppsActionManager.isActionRegistered).isFalse() + } + + @Test + fun changeHome_sameAsOverviewBeforeActionUnregistered_actionRegisteredAgain() { + allAppsActionManager.isHomeAndOverviewSame = true // Initialize to same. + assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue() + + allAppsActionManager.isHomeAndOverviewSame = false + allAppsActionManager.isHomeAndOverviewSame = true + assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue() + assertThat(allAppsActionManager.isActionRegistered).isTrue() + } +} From c53d86ba94d44eebeba0827a0fb3580c80abd1d4 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 26 Mar 2024 13:44:56 -0700 Subject: [PATCH 020/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Bug: 328603775 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b06d115b1fb261636dbe99e69fbf9d846ce77413) Merged-In: Ic2989766561a25c68064303d71578201910bcf72 Change-Id: Ic2989766561a25c68064303d71578201910bcf72 --- quickstep/res/values-as/strings.xml | 4 ++-- quickstep/res/values-bg/strings.xml | 2 +- quickstep/res/values-bs/strings.xml | 2 +- quickstep/res/values-cs/strings.xml | 2 +- quickstep/res/values-de/strings.xml | 2 +- quickstep/res/values-en-rAU/strings.xml | 2 +- quickstep/res/values-en-rGB/strings.xml | 2 +- quickstep/res/values-en-rIN/strings.xml | 2 +- quickstep/res/values-es-rUS/strings.xml | 2 +- quickstep/res/values-es/strings.xml | 2 +- quickstep/res/values-fr-rCA/strings.xml | 2 +- quickstep/res/values-hi/strings.xml | 2 +- quickstep/res/values-hr/strings.xml | 2 +- quickstep/res/values-hy/strings.xml | 2 +- quickstep/res/values-in/strings.xml | 2 +- quickstep/res/values-is/strings.xml | 2 +- quickstep/res/values-it/strings.xml | 2 +- quickstep/res/values-kn/strings.xml | 2 +- quickstep/res/values-ko/strings.xml | 2 +- quickstep/res/values-ky/strings.xml | 2 +- quickstep/res/values-ne/strings.xml | 4 ++-- quickstep/res/values-pa/strings.xml | 2 +- quickstep/res/values-pt/strings.xml | 2 +- quickstep/res/values-te/strings.xml | 4 ++-- quickstep/res/values-tr/strings.xml | 4 ++-- quickstep/res/values-uk/strings.xml | 2 +- quickstep/res/values-vi/strings.xml | 2 +- quickstep/res/values-zh-rHK/strings.xml | 2 +- quickstep/res/values-zh-rTW/strings.xml | 2 +- res/values-af/strings.xml | 13 +++++-------- res/values-am/strings.xml | 9 +++------ res/values-ar/strings.xml | 9 +++------ res/values-as/strings.xml | 11 ++++------- res/values-az/strings.xml | 9 +++------ res/values-b+sr+Latn/strings.xml | 9 +++------ res/values-be/strings.xml | 9 +++------ res/values-bg/strings.xml | 9 +++------ res/values-bn/strings.xml | 11 ++++------- res/values-bs/strings.xml | 9 +++------ res/values-ca/strings.xml | 9 +++------ res/values-cs/strings.xml | 9 +++------ res/values-da/strings.xml | 9 +++------ res/values-de/strings.xml | 9 +++------ res/values-el/strings.xml | 9 +++------ res/values-en-rAU/strings.xml | 9 +++------ res/values-en-rCA/strings.xml | 9 +++------ res/values-en-rGB/strings.xml | 9 +++------ res/values-en-rIN/strings.xml | 9 +++------ res/values-en-rXC/strings.xml | 9 +++------ res/values-es-rUS/strings.xml | 15 ++++++--------- res/values-es/strings.xml | 11 ++++------- res/values-et/strings.xml | 9 +++------ res/values-eu/strings.xml | 11 ++++------- res/values-fa/strings.xml | 9 +++------ res/values-fi/strings.xml | 9 +++------ res/values-fr-rCA/strings.xml | 13 +++++-------- res/values-fr/strings.xml | 9 +++------ res/values-gl/strings.xml | 9 +++------ res/values-gu/strings.xml | 9 +++------ res/values-hi/strings.xml | 9 +++------ res/values-hr/strings.xml | 9 +++------ res/values-hu/strings.xml | 9 +++------ res/values-hy/strings.xml | 9 +++------ res/values-in/strings.xml | 9 +++------ res/values-is/strings.xml | 9 +++------ res/values-it/strings.xml | 9 +++------ res/values-iw/strings.xml | 11 ++++------- res/values-ja/strings.xml | 9 +++------ res/values-ka/strings.xml | 9 +++------ res/values-kk/strings.xml | 9 +++------ res/values-km/strings.xml | 9 +++------ res/values-kn/strings.xml | 9 +++------ res/values-ko/strings.xml | 9 +++------ res/values-ky/strings.xml | 9 +++------ res/values-lo/strings.xml | 9 +++------ res/values-lt/strings.xml | 9 +++------ res/values-lv/strings.xml | 11 ++++------- res/values-mk/strings.xml | 9 +++------ res/values-ml/strings.xml | 9 +++------ res/values-mn/strings.xml | 9 +++------ res/values-mr/strings.xml | 9 +++------ res/values-ms/strings.xml | 9 +++------ res/values-my/strings.xml | 9 +++------ res/values-nb/strings.xml | 9 +++------ res/values-ne/strings.xml | 15 ++++++--------- res/values-nl/strings.xml | 13 +++++-------- res/values-or/strings.xml | 9 +++------ res/values-pa/strings.xml | 9 +++------ res/values-pl/strings.xml | 9 +++------ res/values-pt-rPT/strings.xml | 11 ++++------- res/values-pt/strings.xml | 9 +++------ res/values-ro/strings.xml | 9 +++------ res/values-ru/strings.xml | 9 +++------ res/values-si/strings.xml | 9 +++------ res/values-sk/strings.xml | 9 +++------ res/values-sl/strings.xml | 9 +++------ res/values-sq/strings.xml | 9 +++------ res/values-sr/strings.xml | 9 +++------ res/values-sv/strings.xml | 11 ++++------- res/values-sw/strings.xml | 9 +++------ res/values-ta/strings.xml | 11 ++++------- res/values-te/strings.xml | 9 +++------ res/values-th/strings.xml | 9 +++------ res/values-tl/strings.xml | 9 +++------ res/values-tr/strings.xml | 9 +++------ res/values-uk/strings.xml | 11 ++++------- res/values-ur/strings.xml | 9 +++------ res/values-uz/strings.xml | 9 +++------ res/values-vi/strings.xml | 9 +++------ res/values-zh-rCN/strings.xml | 9 +++------ res/values-zh-rHK/strings.xml | 9 +++------ res/values-zh-rTW/strings.xml | 9 +++------ res/values-zu/strings.xml | 9 +++------ 113 files changed, 307 insertions(+), 559 deletions(-) diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml index 88c50e0b07..4a05bff76f 100644 --- a/quickstep/res/values-as/strings.xml +++ b/quickstep/res/values-as/strings.xml @@ -113,8 +113,8 @@ "আপোনাৰ ৰুটিনৰ ওপৰত আধাৰিত এপৰ পৰামৰ্শ পাওক" "টাস্কবাৰ পিন কৰিবলৈ বিভাজকত দীঘলীয়া সময় টিপি থাকক" "টাস্কবাৰৰ জৰিয়তে অধিক কাৰ্য সম্পাদন কৰক" - "টাস্কবাৰটো সদায় দেখুৱাওক" - "আপোনাৰ স্ক্ৰীণৰ তলত সদায় টাস্কবাৰটো দেখুৱাবলৈ বিভাজকডাল স্পৰ্শ কৰি ধৰি ৰাখক" + "টাস্কবাৰডাল সদায় দেখুৱাওক" + "আপোনাৰ স্ক্ৰীনৰ তলত সদায় টাস্কবাৰডাল দেখুৱাবলৈ বিভাজকডাল স্পৰ্শ কৰি ধৰি ৰাখক" "বন্ধ কৰক" "হ’ল" "গৃহপৃষ্ঠা" diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index d1f59e80ab..59de8defb7 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -113,7 +113,7 @@ "Получавайте предложения за приложения според навиците си" "Натиснете продължително разделителя, за да фиксирате лентата на задачите" "Правете повече неща с лентата на задачите" - "Постоянно показване на лентата на задачите" + "Лентата на задачите да се показва винаги" "За да фиксирате лентата на задачите най-долу на екрана, докоснете и задръжте разделителя" "Затваряне" "Готово" diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml index eb777b4287..549091f885 100644 --- a/quickstep/res/values-bs/strings.xml +++ b/quickstep/res/values-bs/strings.xml @@ -113,7 +113,7 @@ "Dobijajte prijedloge aplikacija zasnovane na vašoj rutini" "Pritisnite i zadržite razdjelnik da zakačite traku zadataka" "Uradite više pomoću trake zadataka" - "Stalan prikaz trake zadataka" + "Stalni prikaz trake zadataka" "Da se traka zadataka uvijek prikazuje na dnu ekrana, dodirnite i zadržite razdjelnik" "Zatvori" "Gotovo" diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index 151a09a04e..96c0b4b027 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -114,7 +114,7 @@ "Dlouhým stisknutím oddělovače připnete panel aplikací" "Více možností s panelem aplikací" "Stálé zobrazení panelu aplikací" - "Pokud chcete ve spodní části obrazovky stále zobrazovat panel aplikací, podržte oddělovač" + "Pokud chcete, aby se panel aplikací vždy zobrazoval ve spodní části obrazovky, podržte oddělovač." "Zavřít" "Hotovo" "Domů" diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index 926fef2ee2..f09e78cb54 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -133,7 +133,7 @@ "Taskleisten-Teiler" "Nach oben / Nach links verschieben" "Nach unten / Nach rechts verschieben" - "{count,plural, =1{# weitere App anzeigen.}other{# weitere Apps anzeigen.}}" + "{count,plural, =1{# weitere App anzeigen}other{# weitere Apps anzeigen}}" "%1$s und %2$s" "Hinzufügen einer App zum Desktop" "Abbrechen" diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml index 10aeee5e9a..5aa85ca48d 100644 --- a/quickstep/res/values-en-rAU/strings.xml +++ b/quickstep/res/values-en-rAU/strings.xml @@ -114,7 +114,7 @@ "Long press on the divider to pin the Taskbar" "Do more with the Taskbar" "Always show the Taskbar" - "To always show the Taskbar on the bottom of your screen, touch & hold the divider" + "To always show the Taskbar on the bottom of your screen, touch and hold the divider" "Close" "Done" "Home" diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml index 10aeee5e9a..5aa85ca48d 100644 --- a/quickstep/res/values-en-rGB/strings.xml +++ b/quickstep/res/values-en-rGB/strings.xml @@ -114,7 +114,7 @@ "Long press on the divider to pin the Taskbar" "Do more with the Taskbar" "Always show the Taskbar" - "To always show the Taskbar on the bottom of your screen, touch & hold the divider" + "To always show the Taskbar on the bottom of your screen, touch and hold the divider" "Close" "Done" "Home" diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml index 10aeee5e9a..5aa85ca48d 100644 --- a/quickstep/res/values-en-rIN/strings.xml +++ b/quickstep/res/values-en-rIN/strings.xml @@ -114,7 +114,7 @@ "Long press on the divider to pin the Taskbar" "Do more with the Taskbar" "Always show the Taskbar" - "To always show the Taskbar on the bottom of your screen, touch & hold the divider" + "To always show the Taskbar on the bottom of your screen, touch and hold the divider" "Close" "Done" "Home" diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index 6fd4cc3e33..213aff50bb 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -114,7 +114,7 @@ "Mantén presionado el divisor para fijar la Barra de tareas" "Aprovecha mejor la Barra de tareas" "Mostrar siempre la Barra de tareas" - "Mantén presionado el divisor para mostrar la Barra de tareas" + "Mantén presionado el divisor para mostrar siempre la Barra de tareas en la parte inferior de la pantalla" "Cerrar" "Listo" "Botón de inicio" diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index 994ad6c16c..64d01a4db2 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -114,7 +114,7 @@ "Mantén pulsado el divisor para fijar la barra de tareas" "Sácale más partido a la barra de tareas" "Mostrar siempre la barra de tareas" - "Para mostrar siempre la barra de tareas, mantén pulsada la línea divisoria" + "Para mostrar siempre la barra de tareas en la parte inferior, mantén pulsada la línea divisoria" "Cerrar" "Hecho" "Inicio" diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index 95caefdbc9..68ca935516 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -114,7 +114,7 @@ "Maintenez le doigt sur le séparateur pour épingler la barre des tâches" "Faites-en plus avec la barre des tâches" "Toujours afficher la Barre des tâches" - "Touj. afficher Barre des tâches en bas de l\'écran : maint. le doigt sur le séparat." + "Pour toujours afficher la Barre des tâches en bas de l\'écran, maintenez le doigt sur le séparateur" "Fermer" "OK" "Accueil" diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 2a97eb1a02..1216746a4f 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -114,7 +114,7 @@ "टास्कबार को पिन करने के लिए डिवाइडर को दबाकर रखें" "टास्कबार की मदद से कई और काम करें" "टास्कबार को हमेशा दिखाएं" - "स्क्रीन के नीचे टास्कबार दिखाने के लिए, डिवाइडर दबाकर रखें" + "टास्कबार को हमेशा अपनी स्क्रीन के नीचे दिखाने के लिए, डिवाइडर दबाकर रखें" "बंद करें" "हो गया" "होम" diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index ee52d99730..26ae082ae9 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -133,7 +133,7 @@ "Razdjelnik trake sa zadacima" "Premjesti gore/lijevo" "Premjesti dolje/desno" - "{count,plural, =1{Prikaži više aplikacija (još #).}one{Prikaži više aplikacija (još #).}few{Prikaži više aplikacija (još #).}other{Prikaži više aplikacija (još #).}}" + "{count,plural, =1{Prikaži još # aplikaciju}one{Prikaži još # aplikaciju}few{Prikaži još # aplikacije}other{Prikaži još # aplikacija}}" "%1$s i %2$s" "Dodavanje aplikacije na radnu površinu" "Odustani" diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml index c770564f14..af613a6e9b 100644 --- a/quickstep/res/values-hy/strings.xml +++ b/quickstep/res/values-hy/strings.xml @@ -114,7 +114,7 @@ "Հավելվածների վահանակն ամրացնելու համար երկար սեղմեք բաժանարարի վրա" "Օգտվեք հավելվածների վահանակի բոլոր հնարավորություններից" "Ամրացրեք հավելվածների վահանակը" - "Էկրանի ներքևում հավելվածների վահանակն ամրացնելու համար երկար հպեք բաժանիչին" + "Հավելվածների վահանակն էկրանի ներքևում ամրացնելու համար հպեք և պահեք բաժանիչը" "Փակել" "Պատրաստ է" "Սկիզբ" diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml index 12ebae0f34..5ced56f194 100644 --- a/quickstep/res/values-in/strings.xml +++ b/quickstep/res/values-in/strings.xml @@ -133,7 +133,7 @@ "Pemisah Taskbar" "Pindahkan ke atas/kiri" "Pindahkan ke bawah/kanan" - "{count,plural, =1{Tampilkan # aplikasi lain.}other{Tampilkan # aplikasi lain.}}" + "{count,plural, =1{Tampilkan # aplikasi lainnya.}other{Tampilkan # aplikasi lainnya.}}" "%1$s dan %2$s" "Menambahkan aplikasi ke Desktop" "Batalkan" diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index ae809a538b..09249bc1dd 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -113,7 +113,7 @@ "Fáðu forritatillögur sem byggjast á rútínunni þinni" "Haltu skiptingu forritastikunnar inni til að festa hana" "Nýttu forritastikuna betur" - "Haltu forritastikunni sýnilegri" + "Halda forritastikunni sýnilegri" "Haltu skjáskiptingunni neðst á skjánum inni til að halda forritastikunni sýnilegri" "Loka" "Lokið" diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index b6cc105330..961a2ff7d6 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -128,7 +128,7 @@ "Barra delle app visualizzata" "Barra delle app nascosta" "Barra di navigazione" - "Mostra sempre barra delle app" + "Mostra sempre barra app" "Cambia modalità di navigazione" "Divisore barra delle app" "Sposta in alto/a sinistra" diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml index 2f72dd0132..023f7b5156 100644 --- a/quickstep/res/values-kn/strings.xml +++ b/quickstep/res/values-kn/strings.xml @@ -114,7 +114,7 @@ "ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ಪಿನ್ ಮಾಡಲು ಡಿವೈಡರ್ ಮೇಲೆ ದೀರ್ಘಕಾಲ ಒತ್ತಿರಿ" "ಟಾಸ್ಕ್‌ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ" "ಯಾವಾಗಲೂ ಟಾಸ್ಕ್‌ಬಾರ್ ಅನ್ನು ತೋರಿಸಿ" - "ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದಲ್ಲಿ ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು, ಡಿವೈಡರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ, ಹೋಲ್ಡ್ ಮಾಡಿ" + "ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದಲ್ಲಿ ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು, ಡಿವೈಡರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ" "ಮುಚ್ಚಿರಿ" "ಆಯಿತು" "ಮುಖಪುಟ" diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml index 39f16e8858..b83bfa2e0b 100644 --- a/quickstep/res/values-ko/strings.xml +++ b/quickstep/res/values-ko/strings.xml @@ -114,7 +114,7 @@ "구분선을 길게 눌러 태스크 바를 고정합니다." "태스크 바 최대한 활용하기" "태스크 바 항상 표시" - "화면 하단에 태스크 바를 항상 표시하려면 구분선을 길게 터치" + "화면 하단에 태스크 바를 항상 표시하려면 구분선을 길게 터치하세요." "닫기" "완료" "홈" diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index d90174cf62..c758411e09 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -114,7 +114,7 @@ "Тапшырмалар панелин кадап коюу үчүн бөлгүчтү коё бербей басып туруңуз" "Тапшырмалар тактасы менен көбүрөөк нерселерди аткарыңыз" "Тапшырмалар панелин ар дайым көрсөтүү" - "Экрандын ылдый жагында Тапшырмалар панелин ар дайым көрсөтүү үчүн бөлгүчтү коё бербей басып туруңуз" + "Тапшырмалар панелин экрандын ылдый жагында ар дайым көрсөтүү үчүн бөлгүчтү коё бербей басыңыз" "Жабуу" "Бүттү" "Башкы бет" diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index f7569a13e2..8e2e44f588 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -45,7 +45,7 @@ "सिफारिस गरिएका एपहरू देखाउने सुविधा असक्षम पारिएको छ" "पूर्वानुमान गरिएको एप: %1$s" "आफ्नो डिभाइस रोटेट गर्नुहोस्" - "इसारामार्फत गरिने नेभिगेसनको ट्युटोरियल पूरा गर्न कृपया आफ्नो डिभाइस रोटेट गर्नुहोस्" + "जेस्चर नेभिगेसनको ट्युटोरियल पूरा गर्न कृपया आफ्नो डिभाइस रोटेट गर्नुहोस्" "स्क्रिनको सबैभन्दा दायाँ किनारा वा सबैभन्दा बायाँ किनाराबाट स्वाइप गर्नुहोस्" "स्क्रिनको दायाँ वा बायाँ किनाराबाट मध्य भागसम्म स्वाइप गर्नुहोस् अनि औँला उठाउनुहोस्" "तपाईंले स्क्रिनको दायाँ किनाराबाट स्वाइप गरेर अघिल्लो स्क्रिनमा फर्कने तरिका सिक्नुभयो। अब एउटा एपबाट अर्को एपमा जाने तरिका सिक्नुहोस्।" @@ -72,7 +72,7 @@ "स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्" "स्क्रिनबाट औँला उठाउनुअघि एपको विन्डोमा केही बेर छोइराख्नुहोस्" "सीधै माथितिर स्वाइप गर्नुहोस् अनि रोकिनुहोस्" - "तपाईंले इसाराहरू प्रयोग गर्ने तरिका सिक्नुभयो। इसारा अफ गर्न सेटिङमा जानुहोस्।" + "तपाईंले जेस्चरहरू प्रयोग गर्ने तरिका सिक्नुभयो। इसारा अफ गर्न सेटिङमा जानुहोस्।" "तपाईंले \"एउटा एपबाट अर्को एपमा जानुहोस्\" नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो" "एउटा एपबाट अर्को एपमा जान स्वाइप गर्नुहोस्" "एउटा एपबाट अर्कोमा जान स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्, छोइराख्नुहोस् अनि औँला उठाउनुहोस्।" diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml index 5b52cb775a..2888969b03 100644 --- a/quickstep/res/values-pa/strings.xml +++ b/quickstep/res/values-pa/strings.xml @@ -114,7 +114,7 @@ "ਟਾਸਕਬਾਰ \'ਤੇ ਪਿੰਨ ਕਰਨ ਲਈ ਵਿਭਾਜਕ \'ਤੇ ਦਬਾਈ ਰੱਖੋ" "ਟਾਸਕਬਾਰ ਦਾ ਹੋਰ ਲਾਹਾ ਲਓ" "ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਉਣਾ" - "ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਟਾਸਕਬਾਰ ਨੂੰ ਹਮੇਸ਼ਾਂ ਦਿਖਾਉਣ ਲਈ, ਵੰਡੋ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ" + "ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਉਣ ਲਈ, ਵਿਭਾਜਕ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ" "ਬੰਦ ਕਰੋ" "ਸਮਝ ਲਿਆ" "ਘਰ" diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index c129187506..2fdf05dd2d 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -113,7 +113,7 @@ "Receba sugestões de apps com base na sua rotina" "Mantenha o separador pressionado para fixar a Barra de tarefas" "Aproveite ainda mais a Barra de tarefas" - "Sempre mostrar a Barra de tarefas" + "Sempre mostrar a Barra de tarefas" "Toque e pressione o divisor para sempre mostrar a Barra de tarefas na parte de baixo da tela" "Fechar" "Concluído" diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index efa6a54b0f..1c422037fc 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -113,8 +113,8 @@ "మీ రొటీన్ ఆధారంగా యాప్ సూచనలను పొందండి" "టాస్క్‌బార్‌ను పిన్ చేయడానికి డివైడర్‌ను ఎక్కువసేపు నొక్కండి" "టాస్క్‌బార్‌తో మరిన్ని చేయండి" - "ఎల్లప్పుడూ టాస్క్‌బార్‌ని చూపించండి" - "ఎల్లప్పుడూ మీ స్క్రీన్ దిగువున టాస్క్‌బార్‌ను చూపడానికి, డివైడర్‌ను తాకి, నొక్కి ఉంచండి" + "టాస్క్‌బార్‌ను నిరంతరం చూపండి" + "మీ స్క్రీన్ దిగువున టాస్క్‌బార్‌ను నిరంతరం చూపడానికి, డివైడర్‌ను తాకి, నొక్కి ఉంచండి" "మూసివేయండి" "పూర్తయింది" "మొదటి ట్యాబ్" diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml index 5a45e2988d..cedfa2fd93 100644 --- a/quickstep/res/values-tr/strings.xml +++ b/quickstep/res/values-tr/strings.xml @@ -113,8 +113,8 @@ "Rutininize göre uygulama önerileri alın" "Görev çubuğunu sabitlemek için ayırıcıya uzun basın" "Görev çubuğuyla daha fazla şey yapın" - "Görev çubuğunu her zaman göster" - "Görev çubuğunu, ekranınızın alt tarafında her zaman göstermek için ayırıcıya dokunup basılı tutun" + "Görev çubuğunu sabitleyin" + "Ayırıcıya dokunup basılı tuttuğunuzda görev çubuğu ekranın alt kısmına sabitlenir" "Kapat" "Bitti" "Ana ekran" diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml index c20c213e00..71257c8fbc 100644 --- a/quickstep/res/values-uk/strings.xml +++ b/quickstep/res/values-uk/strings.xml @@ -114,7 +114,7 @@ "Утримуйте розділювач, щоб закріпити панель завдань" "Більше можливостей завдяки панелі завдань" "Завжди показувати панель завдань" - "Щоб завжди показувати панель завдань унизу екрана, натисніть і втримуйте розділювач" + "Щоб завжди показувати панель завдань унизу екрана, натисніть і втримуйте роздільник" "Закрити" "Готово" "Головний екран" diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml index ef6f172ebd..626c569ba5 100644 --- a/quickstep/res/values-vi/strings.xml +++ b/quickstep/res/values-vi/strings.xml @@ -114,7 +114,7 @@ "Nhấn và giữ trên đường phân chia để ghim Thanh tác vụ" "Làm nhiều việc hơn qua Thanh tác vụ" "Luôn hiện Taskbar" - "Để luôn hiện Taskbar ở cuối màn hình, hãy nhấn và giữ trên đường phân chia" + "Để luôn hiện Taskbar ở cuối màn hình, hãy nhấn và giữ đường phân chia" "Đóng" "Xong" "Màn hình chính" diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index b0f44b2e0d..d01211dbb0 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -113,7 +113,7 @@ "獲取符合日常習慣的應用程式建議" "長按分隔線即可固定工作列" "工作列助你事半功倍" - "永遠顯示工作列" + "一律顯示工作列" "如要持續在畫面底部顯示工作列,請按住分隔線" "關閉" "完成" diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index 2190c54dcf..142f8832cb 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -133,7 +133,7 @@ "工作列分隔線" "移到上方/左側" "移到底部/右側" - "{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}" + "{count,plural, =1{再多顯示 # 個應用程式。}other{再多顯示 # 個應用程式。}}" "「%1$s」和「%2$s」" "新增應用程式至桌面" "取消" diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index e733104db2..1e1b3f3a3a 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -31,10 +31,8 @@ "Programinligting vir %1$s" "Stoor apppaar" "%1$s | %2$s" - - - - + "Hierdie apppaar word nie op hierdie toestel gesteun nie" + "Vou die toestel oop om hierdie apppaar te gebruik" "Raak en hou om \'n legstuk te skuif." "Dubbeltik en hou om \'n legstuk te skuif of gebruik gepasmaakte handelinge." "%1$d × %2$d" @@ -127,8 +125,8 @@ "Verander instellings" "Wys kennisgewingkolle" "Ontwikkelaaropsies" - "Voeg programikone by tuisskerm" - "Vir nuwe programme" + "Voeg appikone by tuisskerm" + "Vir nuwe apps" "Onbekend" "Verwyder" "Soek" @@ -137,8 +135,7 @@ "%1$s installeer tans; %2$s voltooi" "%1$s laai tans af, %2$s voltooid" "%1$s wag tans om te installeer" - - + "%1$s is geargiveer. Tik om af te laai." "Programopdatering word vereis" "Die program vir hierdie ikoon is nie opgedateer nie. Jy kan dit handmatig opdateer om hierdie kortpad weer te aktiveer, of die ikoon verwyder." "Dateer op" diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index 1c9a729d13..e404506a43 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -31,10 +31,8 @@ "የመተግበሪያ መረጃ ለ%1$s" "የመተግበሪያ ጥምረትን ያስቀምጡ" "%1$s | %2$s" - - - - + "ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም" + "ይህን የመተግበሪያ ጥምረት ለመጠቀም መሣሪያን ይዘርጉ" "ምግብርን ለማንቀሳቀስ ይንኩ እና ይያዙ።" "ምግብርን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።" "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s በመጫን ላይ፣ %2$s ተጠናቅቋል" "%1$s በመውረድ ላይ፣ %2$s ተጠናቋል" "%1$s ለመጫን በመጠበቅ ላይ" - - + "%1$s በማህደር ተቀምጧል። ለማውረድ መታ ያድርጉ።" "መተግበሪያ ማዘመን አስፈላጊ ነው" "የዚህ አዶ መተግበሪያ አልተዘመነም። ይህን አቋራጭ ዳግም ለማንቃት በራስዎ ማዘመን ወይም አዶውን ማስወገድ ይችላሉ።" "አዘምን" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 4624784ad3..e1b98fb5c3 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -31,10 +31,8 @@ "‏معلومات تطبيق %1$s" "حفظ إعدادات ميزة \"استخدام تطبيقين في الوقت نفسه\"" "%1$s | ‏%2$s" - - - - + "لا يمكن استخدام هذين التطبيقَين في الوقت نفسه على هذا الجهاز" + "افتح الجهاز لاستخدام هذين التطبيقَين في الوقت نفسه" "انقر مع الاستمرار لنقل أداة." "انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة." "%1$d × %2$d" @@ -137,8 +135,7 @@ "جارٍ تثبيت %1$s، مستوى التقدم: %2$s" "جارٍ تنزيل %1$s، اكتمل %2$s" "%1$s في انتظار التثبيت" - - + "تمت أرشفة تطبيق %1$s. انقر للتنزيل." "مطلوب تحديث التطبيق" "لم يتمّ تحديث التطبيق الخاص بهذا الرمز. يمكنك تحديث التطبيق يدويًا لإعادة تفعيل هذا الاختصار أو إزالة الرمز." "تحديث" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index 3deac7eb40..940e2dbcda 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -31,10 +31,8 @@ "%1$sৰ বাবে এপৰ তথ্য" "এপৰ পেয়াৰ ছেভ কৰক" "%1$s | %2$s" - - - - + "এই ডিভাইচটোত এই এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো সমৰ্থিত নহয়" + "এই এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো ব্যৱহাৰ কৰিবলৈ ডিভাইচটো আনফ’ল্ড কৰক" "ৱিজেট স্থানান্তৰ কৰিবলৈ টিপি ধৰি ৰাখক।" "কোনো ৱিজেট স্থানান্তৰ কৰিবলৈ দুবাৰ টিপি ধৰি ৰাখক অথবা কাষ্টম কাৰ্য ব্যৱহাৰ কৰক।" "%1$d × %2$d" @@ -120,7 +118,7 @@ "গৃহ স্ক্ৰীন ঘূৰোৱাৰ অনুমতি দিয়ক" "ফ\'নটো যেতিয়া ঘূৰোৱা হয়" "জাননী বিন্দু" - "অন আছে" + "অন কৰা আছে" "অফ আছে" "জাননীৰ এক্সেছৰ প্ৰয়োজন" "জাননী সম্পৰ্কীয় বিন্দুবোৰ দেখুৱাবলৈ %1$sৰ বাবে এপৰ জাননীসমূহ অন কৰক" @@ -137,8 +135,7 @@ "%1$s ইনষ্টল কৰি থকা হৈছে, %2$s সম্পূৰ্ণ হৈছে" "%1$s ডাউনল’ড কৰি থকা হৈছে, %2$s সম্পূৰ্ণ হ’ল" "%1$s ইনষ্টল হোৱালৈ অপেক্ষা কৰি থকা হৈছে" - - + "%1$s আৰ্কাইভ কৰা হৈছে। ডাউনল’ড কৰিবলৈ টিপক।" "এপ্‌টো আপডে’ট কৰা প্ৰয়োজন" "এই চিহ্নটোৰ এপ্‌টো আপডে’ট কৰা হোৱা নাই। আপুনি এই শ্বৰ্টকাটটো পুনৰ সক্ষম কৰিবলৈ মেনুৱেলী আপডে’ট কৰিব পাৰে অথবা চিহ্নটো আঁতৰাব পাৰে।" "আপডে’ট কৰক" diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 966fe9bebb..d11c4a7225 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -31,10 +31,8 @@ "%1$s ilə bağlı tətbiq məlumatı" "Tətbiq cütünü saxlayın" "%1$s | %2$s" - - - - + "Bu tətbiq cütü bu cihazda dəstəklənmir" + "Bu tətbiq cütündən istifadə üçün cihazı açın" "Vidceti daşımaq üçün toxunub saxlayın." "Vidceti daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s quraşdırır, %2$s tamamlanıb" "%1$s endirilir, %2$s tamamlandı" "%1$s yüklənmək üçün gözləyir" - - + "%1$s arxivləndi. Endirmək üçün toxunun." "Tətbiqin güncəllənməsi tələb edilir" "Bu ikona üçün tətbiq güncəllənməyib. Bu qısayolu yenidən aktivləşdirmək üçün manual olaraq güncəlləyə və ya ikonanı silə bilərsiniz." "Güncəlləyin" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 2e08d5cf07..b99ec65e39 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -31,10 +31,8 @@ "Informacije o aplikaciji za: %1$s" "Sačuvaj par aplikacija" "%1$s | %2$s" - - - - + "Ovaj par aplikacija nije podržan na ovom uređaju" + "Otvorite uređaj da biste koristili ovaj par aplikacija" "Dodirnite i zadržite radi pomeranja vidžeta." "Dvaput dodirnite i zadržite da biste pomerali vidžet ili koristite prilagođene radnje." "%1$d×%2$d" @@ -137,8 +135,7 @@ "%1$s se instalira, %2$s gotovo" "%1$s se preuzima, završeno je %2$s" "%1$s čeka na instaliranje" - - + "Aplikacija %1$s je arhivirana. Dodirnite da biste je preuzeli." "Treba da ažurirate aplikaciju" "Aplikacija za ovu ikonu nije ažurirana. Možete da je ručno ažurirate da biste ponovo omogućili ovu prečicu ili uklonite ikonu." "Ažuriraj" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 6c4c6dd714..c9784256fb 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -31,10 +31,8 @@ "Інфармацыя пра праграму для: %1$s" "Захаваць спалучэнне праграм" "%1$s | %2$s" - - - - + "Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе" + "Каб выкарыстоўваць гэта спалучэнне праграм, раскладзіце прыладу" "Націсніце і ўтрымлівайце віджэт для перамяшчэння." "Дакраніцеся двойчы і ўтрымлівайце, каб перамясціць віджэт або выкарыстоўваць спецыяльныя дзеянні." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Усталёўваецца праграма \"%1$s\", завершана %2$s" "Ідзе спампоўка %1$s, %2$s завершана" "%1$s чакае ўсталёўкі" - - + "Праграма \"%1$s\" знаходзіцца ў архіве. Націсніце, каб спампаваць." "Неабходна абнавіць праграму" "Гэта версія праграмы састарэла. Абнавіце праграму ўручную, каб зноў карыстацца гэтым ярлыком, або выдаліце значок." "Абнавіць" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index b3882976f8..769c538924 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -31,10 +31,8 @@ "Информация за приложението за %1$s" "Запазване на двойката приложения" "%1$s | %2$s" - - - - + "Тази двойка приложения не се поддържа на устройството" + "Отворете устройството, за да използвате тази двойка приложения" "Докоснете и задръжте за преместване на приспособление" "Докоснете двукратно и задръжте за преместване на приспособление или използвайте персонал. действия." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s се инсталира, %2$s завършено" "%1$s се изтегля. Завършено: %2$s" "%1$s изчаква инсталиране" - - + "Приложението %1$s е архивирано. Докоснете за изтегляне." "Изисква се актуализация на приложението" "Приложението за тази икона не е актуализирано. Можете да го актуализирате ръчно, за да активирате отново този пряк път, или да премахнете иконата." "Актуализиране" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index e71b5784f0..cc6a8aac90 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -31,10 +31,8 @@ "%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য" "অ্যাপ পেয়ার সেভ করুন" "%1$s | %2$s" - - - - + "এই ডিভাইসে এই অ্যাপ পেয়ারটি কাজ করে না" + "এই অ্যাপ পেয়ার ব্যবহার করতে ডিভাইস আনফোল্ড করুন" "কোনও উইজেট সরাতে সেটি টাচ করে ধরে রাখুন।" "একটি উইজেট সরাতে বা কাস্টম অ্যাকশন ব্যবহার করতে ডবল ট্যাপ করে ধরে রাখুন।" "%1$d × %2$d" @@ -120,7 +118,7 @@ "হোম স্ক্রিন রোটেট করার অনুমতি দিন" "যখন ফোনটি ঘোরানো হয়" "বিজ্ঞপ্তি ডট" - "চালু" + "চালু করা আছে" "বন্ধ" "বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন" "বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, %1$s এর অ্যাপ বিজ্ঞপ্তি চালু করুন" @@ -137,8 +135,7 @@ "%1$s ইনস্টল করা হচ্ছে, %2$s সম্পূর্ণ হয়েছে" "%1$s ডাউনলোড হচ্ছে %2$s সম্পন্ন হয়েছে" "%1$s ইনস্টলের অপেক্ষায় রয়েছে" - - + "%1$s আর্কাইভ করা হয়েছে। ডাউনলোড করতে ট্যাপ করুন।" "অ্যাপটি আপডেট করা প্রয়োজন" "এই আইকনের জন্য অ্যাপটি আপডেট করা নেই। এই শর্টকার্ট আবার চালু করতে, আপনি ম্যানুয়ালি আপডেট করতে বা সরিয়ে দিতে পারবেন।" "আপডেট করুন" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index fd143bfee9..0c4356174d 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -31,10 +31,8 @@ "Informacije o aplikaciji %1$s" "Sačuvaj par aplikacija" "%1$s | %2$s" - - - - + "Par aplikacija nije podržan na uređaju" + "Otklopite uređaj da koristite ovaj par aplikacija" "Dodirnite i zadržite da pomjerite vidžet." "Dvaput dodirnite i zadržite da pomjerite vidžet ili da koristite prilagođene radnje." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Instaliranje aplikacije %1$s, završeno je %2$s" "%1$s se preuzima, završeno %2$s" "%1$s čeka da se instalira" - - + "Arhivirana je aplikacija %1$s. Dodirnite je da je preuzmete." "Potrebno je ažurirati aplikaciju" "Aplikacija za ovu ikonu nije ažurirana. Možete je ažurirati ručno da ponovo omogućite ovu prečicu ili možete ukloniti ikonu." "Ažuriraj" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index f970e2c3a8..37d8626f9a 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -31,10 +31,8 @@ "Informació de l\'aplicació %1$s" "Desa la parella d\'aplicacions" "%1$s | %2$s" - - - - + "Aquesta parella d\'aplicacions no s\'admet en aquest dispositiu" + "Desplega el dispositiu per utilitzar aquesta parella d\'aplicacions" "Fes doble toc i mantén premut per moure un widget." "Fes doble toc i mantén premut per moure un widget o per utilitzar accions personalitzades." "%1$d × %2$d" @@ -137,8 +135,7 @@ "S\'està instal·lant %1$s; s\'ha completat un %2$s" "S\'està baixant %1$s, %2$s completat" "S\'està esperant per instal·lar %1$s" - - + "L\'aplicació %1$s està arxivada. Toca per baixar." "Cal actualitzar l\'aplicació" "L\'aplicació d\'aquesta icona no està actualitzada. Pots actualitzar-la manualment per tornar a activar aquesta drecera o pots suprimir la icona." "Actualitza" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 329405efae..2def07ca44 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -31,10 +31,8 @@ "Informace o aplikaci %1$s" "Uložit pár aplikací" "%1$s | %2$s" - - - - + "Tento pár aplikací není na tomto zařízení podporován" + "Pokud chcete použít tento pár aplikací, rozložte zařízení" "Widget přesunete klepnutím a podržením." "Dvojitým klepnutím a podržením přesunete widget, případně použijte vlastní akce." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Instalace aplikace %1$s, dokončeno %2$s" "Stahování aplikace %1$s (dokončeno %2$s)" "Instalace aplikace %1$s čeká na zahájení" - - + "Aplikace %1$s je archivována. Klepnutím ji stáhnete." "Je nutná aktualizace aplikace" "Aplikace pro tuto ikonu není nainstalována. Můžete ji ručně aktualizovat, aby zkratka znovu fungovala, případně můžete ikonu odstranit." "Aktualizovat" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 64618a7171..57053e6856 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -31,10 +31,8 @@ "Appinfo for %1$s" "Gem appsammenknytning" "%1$s | %2$s" - - - - + "Denne appsammenknytning understøttes ikke på enheden" + "Fold enheden ud for at bruge denne appsammenknytning" "Hold en widget nede for at flytte den." "Tryk to gange, og hold en widget nede for at flytte den eller bruge tilpassede handlinger." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s installeres. %2$s fuldført" "%1$s downloades. %2$s er gennemført" "%1$s venter på at installere" - - + "%1$s er arkiveret Tryk for at downloade." "Appen skal opdateres" "Appen, der tilhører dette ikon, er ikke opdateret. Du kan opdatere appen manuelt for at genaktivere denne genvej, eller du kan fjerne ikonet." "Opdater" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 7f520f26b3..5eff0b058c 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -31,10 +31,8 @@ "App-Info für %1$s" "App-Paar speichern" "%1$s | %2$s" - - - - + "Dieses App-Paar wird auf diesem Gerät nicht unterstützt" + "Gerät aufklappen, um dieses App-Paar zu verwenden" "Zum Verschieben des Widgets berühren und halten" "Doppeltippen und halten, um ein Widget zu bewegen oder benutzerdefinierte Aktionen zu nutzen." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s wird installiert, %2$s abgeschlossen" "%1$s wird heruntergeladen, %2$s abgeschlossen" "Warten auf Installation von %1$s" - - + "%1$s ist archiviert. Zum Herunterladen tippen." "App-Update erforderlich" "Die App für dieses Symbol wurde noch nicht aktualisiert. Du kannst sie manuell aktualisieren, um die Verknüpfung wieder zu aktivieren, oder das Symbol entfernen." "Aktualisieren" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index d85543d719..d868040aca 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -31,10 +31,8 @@ "Πληροφορίες εφαρμογής για %1$s" "Αποθήκευση ζεύγους εφαρμογών" "%1$s | %2$s" - - - - + "Αυτό το ζεύγος εφαρμογών δεν υποστηρίζεται σε αυτή τη συσκευή" + "Ξεδιπλώστε τη συσκευή για να χρησιμοποιήσετε αυτό το ζεύγος εφαρμογών" "Πατήστε παρατετ. για μετακίνηση γραφ. στοιχείου." "Πατήστε δύο φορές παρατεταμένα για μετακίνηση γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Έχει ολοκληρωθεί το %2$s της εγκατάστασης της εφαρμογής %1$s" "Λήψη %1$s, ολοκληρώθηκε %2$s" "%1$s σε αναμονή για εγκατάσταση" - - + "Η εφαρμογή %1$s είναι αρχειοθετημένη. Πατήστε για λήψη." "Απαιτείται ενημέρωση της εφαρμογής" "Η εφαρμογή για αυτό το εικονίδιο δεν έχει ενημερωθεί. Μπορείτε να την ενημερώσετε μη αυτόματα για να ενεργοποιήσετε ξανά τη συγκεκριμένη συντόμευση ή να καταργήσετε το εικονίδιο." "Ενημέρωση" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 45af2c5dc6..cee4d2ac58 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -31,10 +31,8 @@ "App info for %1$s" "Save app pair" "%1$s | %2$s" - - - - + "This app pair isn\'t supported on this device" + "Unfold device to use this app pair" "Touch and hold to move a widget." "Double-tap & hold to move a widget or use custom actions." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s installing, %2$s complete" "%1$s downloading, %2$s complete" "%1$s waiting to install" - - + "%1$s is archived. Tap to download." "App update required" "The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon." "Update" diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index e997044693..87cd9eb110 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -31,10 +31,8 @@ "App info for %1$s" "Save app pair" "%1$s | %2$s" - - - - + "This app pair isn\'t supported on this device" + "Unfold device to use this app pair" "Touch and hold to move a widget." "Double-tap and hold to move a widget or use custom actions." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s installing, %2$s complete" "%1$s downloading, %2$s complete" "%1$s waiting to install" - - + "%1$s is archived. Tap to download." "App update required" "The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon." "Update" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 45af2c5dc6..cee4d2ac58 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -31,10 +31,8 @@ "App info for %1$s" "Save app pair" "%1$s | %2$s" - - - - + "This app pair isn\'t supported on this device" + "Unfold device to use this app pair" "Touch and hold to move a widget." "Double-tap & hold to move a widget or use custom actions." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s installing, %2$s complete" "%1$s downloading, %2$s complete" "%1$s waiting to install" - - + "%1$s is archived. Tap to download." "App update required" "The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon." "Update" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 45af2c5dc6..cee4d2ac58 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -31,10 +31,8 @@ "App info for %1$s" "Save app pair" "%1$s | %2$s" - - - - + "This app pair isn\'t supported on this device" + "Unfold device to use this app pair" "Touch and hold to move a widget." "Double-tap & hold to move a widget or use custom actions." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s installing, %2$s complete" "%1$s downloading, %2$s complete" "%1$s waiting to install" - - + "%1$s is archived. Tap to download." "App update required" "The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon." "Update" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index ae8664107b..ae84841eb1 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -31,10 +31,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎App info for %1$s‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‎Save app pair‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ | ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‎‎This app pair isn\'t supported on this device‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‎Unfold device to use this app pair‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎Touch & hold to move a widget.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎Double-tap & hold to move a widget or use custom actions.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎%1$d × %2$d‎‏‎‎‏‎" @@ -137,8 +135,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ installing, ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ complete‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ downloading, ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ complete‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ waiting to install‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ is archived. Tap to download.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎App update required‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎Update‎‏‎‎‏‎" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 9f613a2bce..a7259a2634 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -31,10 +31,8 @@ "Información de la app de %1$s" "Guardar vinculación de apps" "%1$s | %2$s" - - - - + "No se admite esta vinculación de apps en este dispositivo" + "Abre el dispositivo para usar esta vinculación de apps" "Mantén presionado para mover un widget." "Presiona dos veces y mantén presionado para mover un widget o usar acciones personalizadas." "%1$d × %2$d" @@ -120,14 +118,14 @@ "Permitir la rotación de la pantalla principal" "Al girar el teléfono" "Puntos de notificación" - "Activado" - "Desactivado" + "Activados" + "Desactivados" "Se necesita acceso a las notificaciones" "Para mostrar los puntos de notificación, activa las notificaciones de la app para %1$s" "Cambiar la configuración" "Mostrar puntos de notificación" "Opciones para desarrolladores" - "Agrega íconos de las apps a la pantalla principal" + "Agregar íconos de las apps a la pantalla principal" "Para nuevas apps" "Desconocido" "Eliminar" @@ -137,8 +135,7 @@ "Se está instalando %1$s; %2$s completado" "Se completó el %2$s de la descarga de %1$s" "Instalación de %1$s en espera" - - + "%1$s está archivada. Presiona para descargar." "Es necesario actualizar la app" "No se actualizó la app de este ícono. Puedes actualizarla manualmente para rehabilitar el acceso directo, o bien quitar el ícono." "Actualizar" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 8fd21173a3..176bfe368b 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -31,10 +31,8 @@ "Información de la aplicación %1$s" "Guardar aplicaciones emparejadas" "%1$s | %2$s" - - - - + "El dispositivo no admite esta aplicación emparejada" + "Despliega el dispositivo para usar esta aplicación emparejada" "Mantén pulsado un widget para moverlo" "Toca dos veces y mantén pulsado un widget para moverlo o usar acciones personalizadas." "%1$d × %2$d" @@ -128,7 +126,7 @@ "Mostrar puntos de notificación" "Opciones para desarrolladores" "Añadir iconos de aplicaciones a la pantalla de inicio" - "Añade el icono de una aplicación nueva instalada a la pantalla de inicio" + "Para aplicaciones nuevas" "Desconocido" "Quitar" "Buscar" @@ -137,8 +135,7 @@ "Instalando %1$s, %2$s completado" "Descargando %1$s (%2$s completado)" "Esperando para instalar %1$s" - - + "%1$s está archivada. Toca para descargarla." "Debes actualizar la aplicación" "La aplicación de este icono no está actualizada. Puedes actualizarla manualmente para volver a habilitar este acceso directo o puedes eliminar el icono." "Actualizar" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 09744477b0..830abf00a8 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -31,10 +31,8 @@ "Rakenduse teave: %1$s" "Salvesta rakendusepaar" "%1$s | %2$s" - - - - + "See rakendusepaar ei ole selles seadmes toetatud" + "Selle rakendusepaari kasutamiseks voltige seade lahti" "Vidina teisaldamiseks puudutage ja hoidke all." "Vidina teisaldamiseks või kohandatud toimingute kasutamiseks topeltpuudutage ja hoidke all." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Üksust %1$s installitakse, %2$s on valmis" "Rakenduse %1$s allalaadimine, %2$s on valmis" "%1$s on installimise ootel" - - + "%1$s on arhiivitud. Puudutage allalaadimiseks." "Rakendust tuleb värskendada" "Selle ikooni rakendust pole värskendatud. Otsetee uuesti lubamiseks võite rakendust käsitsi värskendada või ikooni eemaldada." "Värskenda" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 8c6bc2204f..f269c25b8f 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -31,10 +31,8 @@ "%1$s aplikazioari buruzko informazioa" "Gorde aplikazio parea" "%1$s | %2$s" - - - - + "Aplikazio pare hori ez da onartzen gailu honetan" + "Zabaldu gailua aplikazio pare hau erabiltzeko" "Eduki sakatuta widget bat mugitzeko." "Sakatu birritan eta eduki sakatuta widget bat mugitzeko edo ekintza pertsonalizatuak erabiltzeko." "%1$d × %2$d" @@ -115,7 +113,7 @@ "Aplikazio parea: %1$s eta %2$s" "Horma-papera eta estiloa" "Editatu orri nagusia" - "Hasierako pantailaren ezarpenak" + "Orri nagusiaren ezarpenak" "Administratzaileak desgaitu du" "Eman orri nagusia biratzeko baimena" "Telefonoa biratzean" @@ -137,8 +135,7 @@ "%1$s instalatzen, %2$s osatuta" "%1$s deskargatzen, %2$s osatuta" "%1$s instalatzeko zain" - - + "%1$s artxibatuta dago. Deskargatzeko, sakatu hau." "Aplikazioa eguneratu egin behar da" "Ikonoaren aplikazioa ez dago eguneratuta. Lasterbidea berriro gaitzeko, eskuz egunera dezakezu aplikazioa. Bestela, kendu ikonoa." "Eguneratu" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index d05feae79f..feaf7242a9 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -31,10 +31,8 @@ "‏اطلاعات برنامه %1$s" "ذخیره جفت برنامه" "%1$s | %2$s" - - - - + "از این جفت برنامه در این دستگاه پشتیبانی نمی‌شود" + "برای استفاده از این جفت برنامه، دستگاه را باز کنید" "برای جابه‌جا کردن ابزارک، لمس کنید و نگه دارید." "برای جابه‌جا کردن ابزارک یا استفاده از کنش‌های سفارشی، دوضربه بزنید و نگه دارید." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s درحال نصب است، %2$s تکمیل شده است" "درحال بارگیری %1$s، %2$s کامل شد" "%1$s درانتظار نصب" - - + "%1$s بایگانی شده است. برای بارگیری ضربه بزنید." "برنامه باید به‌روز شود" "برنامه برای این نماد به‌روز نشده است. می‌توانید آن را به‌صورت دستی به‌روز کنید تا میان‌بر دوباره فعال شود، یا نماد را بردارید." "به‌روزرسانی" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 8b3c160dca..3198a03cbc 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -31,10 +31,8 @@ "Sovellustiedot: %1$s" "Tallenna sovelluspari" "%1$s | %2$s" - - - - + "Sovellusparia ei tueta tällä laitteella" + "Avaa taitettu laite, niin voit käyttää sovellusparia" "Kosketa pitkään, niin voit siirtää widgetiä." "Kaksoisnapauta ja paina pitkään, niin voit siirtää widgetiä tai käyttää muokattuja toimintoja." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s asennetaan, %2$s valmis" "%1$s latautuu, valmiina %2$s" "%1$s odottaa asennusta" - - + "%1$s on arkistoitu. Lataa napauttamalla." "Sovelluspäivitys vaaditaan" "Kuvakkeen sovellusta ei ole päivitetty. Voit ottaa pikakuvakkeen uudelleen käyttöön päivittämällä sovelluksen tai poistaa kuvakkeen." "Päivitä" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index c3b8d99e5f..6ddeeef145 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -27,14 +27,12 @@ "Widgets désactivés en mode sans échec" "Le raccourci n\'est pas disponible" "Accueil" - "Écran partagé" + "Écran divisé" "Renseignements sur l\'appli pour %1$s" "Enregistrer la paire d\'applications" "%1$s | %2$s" - - - - + "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" + "Déplier l\'appareil pour utiliser cette paire d\'applications" "Maintenez le doigt sur un widget pour le déplacer." "Touchez 2x un widget et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées." "%1$d × %2$d" @@ -119,7 +117,7 @@ "Cette fonction est désactivée par votre administrateur" "Autoriser la rotation de l\'écran d\'accueil" "Lorsque vous faites pivoter le téléphone" - "Points de notification" + "Pastilles de notification" "Activé" "Désactivé" "L\'accès aux notifications est requis" @@ -137,8 +135,7 @@ "Installation de l\'application %1$s en cours, %2$s terminée" "Téléchargement de %1$s : %2$s" "%1$s en attente d\'installation" - - + "L\'application %1$s est archivée. Toucher pour télécharger." "Mise à jour de l\'application requise" "L\'application pour cette icône n\'est pas à jour. Vous pouvez soit la mettre à jour manuellement pour réactiver ce raccourci, soit retirer l\'icône." "Mettre à jour" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 60612d6632..fdeae1cb0f 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -31,10 +31,8 @@ "Infos sur l\'appli pour %1$s" "Enregistrer la paire d\'applis" "%1$s | %2$s" - - - - + "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" + "Dépliez l\'appareil pour utiliser cette paire d\'applications" "Appuyez de manière prolongée sur un widget pour le déplacer." "Appuyez deux fois et maintenez la pression pour déplacer widget ou utiliser actions personnalisées." "%1$d x %2$d" @@ -137,8 +135,7 @@ "Installation de %1$s… (%2$s terminés)" "%1$s en cours de téléchargement, %2$s effectué(s)" "%1$s en attente d\'installation" - - + "L\'application %1$s est archivée. Appuyez pour télécharger." "Mise à jour de l\'appli requise" "L\'appli correspondant à cette icône n\'est pas mise à jour. Vous pouvez la mettre à jour manuellement pour réactiver le raccourci ou supprimer l\'icône." "Modifier" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index d10718189a..9388948f47 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -31,10 +31,8 @@ "Información da aplicación para %1$s" "Gardar emparellamento de aplicacións" "%1$s | %2$s" - - - - + "O dispositivo non admite este emparellamento de aplicacións" + "Desprega o dispositivo para usar este emparellamento de aplicacións" "Mantén premido un widget para movelo." "Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Instalando %1$s, %2$s completado" "Descargando %1$s (%2$s completado)" "Esperando para instalar %1$s" - - + "%1$s está no arquivo. Toca para descargar esta aplicación." "É necesario actualizar a aplicación" "A aplicación á que corresponde esta icona non está actualizada. Podes actualizala manualmente para activar de novo este atallo, ou ben quitar a icona." "Actualizar" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 0a79661834..ec6d99495b 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -31,10 +31,8 @@ "%1$s માટે ઍપ માહિતી" "ઍપની જોડી સાચવો" "%1$s | %2$s" - - - - + "આ ડિવાઇસ પર, આ ઍપની જોડીને સપોર્ટ આપવામાં આવતો નથી" + "આ ઍપની જોડીનો ઉપયોગ કરવા માટે, ડિવાઇસને અનફોલ્ડ કરો" "વિજેટ ખસેડવા ટચ કરીને થોડી વાર દબાવી રાખો." "વિજેટ ખસેડવા બે વાર ટૅપ કરીને દબાવી રાખો અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરો." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ઇન્સ્ટૉલ કરી રહ્યાં છીએ, %2$s પૂર્ણ થયું" "%1$s ડાઉનલોડ કરી રહ્યાં છે, %2$s પૂર્ણ" "%1$s, ઇન્સ્ટૉલ થવાની રાહ જોઈ રહ્યું છે" - - + "%1$s આર્કાઇવ કરી છે. ડાઉનલોડ કરવા માટે ટૅપ કરો." "ઍપને અપડેટ કરવી જરૂરી છે" "આ આઇકન માટે ઍપ અપડેટ કરવામાં આવી નથી. તમે આ શૉર્ટકટ ફરી ચાલુ કરવા અથવા આઇકન કાઢી નાખવા માટે ઍપને મેન્યુઅલી અપડેટ કરી શકો છો." "અપડેટ કરો" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index be0d496cae..f0431490da 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -31,10 +31,8 @@ "%1$s के लिए ऐप्लिकेशन की जानकारी" "साथ में इस्तेमाल किए जा सकने वाले ऐप्लिकेशन की जानकारी सेव करें" "%1$s | %2$s" - - - - + "साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन, इस डिवाइस पर काम नहीं कर सकते" + "साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन इस्तेमाल करने के लिए डिवाइस को अनफ़ोल्ड करें" "किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उसे दबाकर रखें." "किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उस पर दो बार टैप करके दबाकर रखें या पसंद के मुताबिक कार्रवाइयां इस्तेमाल करें." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s इंस्टॉल किया जा रहा है, %2$s पूरा हो गया" "%1$s डाउनलोड हो रहा है, %2$s पूरी हुई" "%1$s के इंस्टॉल होने की प्रतीक्षा की जा रही है" - - + "%1$s को संग्रहित किया गया. डाउनलोड करने के लिए टैप करें." "ऐप्लिकेशन को अपडेट करना ज़रूरी है" "इस आइकॉन का ऐप्लिकेशन अपडेट नहीं है. इस शॉर्टकट को फिर से चालू करने या आइकॉन को हटाने के लिए, ऐप्लिकेशन को मैन्युअल रूप से अपडेट किया जा सकता है." "अपडेट करें" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 2ae18df31a..f40252b14b 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -31,10 +31,8 @@ "Informacije o aplikaciji %1$s" "Spremi par aplikacija" "%1$s | %2$s" - - - - + "Taj par aplikacija nije podržan na ovom uređaju" + "Otvorite uređaj da biste upotrebljavali ovaj par aplikacija" "Dodirnite i zadržite da biste premjestili widget." "Dvaput dodirnite i zadržite pritisak da biste premjestili widget ili upotrijebite prilagođene radnje" "%1$d × %2$d" @@ -137,8 +135,7 @@ "Instaliranje aplikacije %1$s, %2$s dovršeno" "Preuzimanje aplikacije %1$s, dovršeno %2$s" "Čekanje na instaliranje aplikacije %1$s" - - + "Aplikacija %1$s je arhivirana. Dodirnite za preuzimanje." "Aplikacija se treba ažurirati" "Aplikacija ove ikone nije ažurirana. Možete ručno ažurirati da biste ponovo omogućili ovaj prečac ili uklonite ikonu." "Ažuriraj" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 6e2cfe6289..6fc5f286da 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -31,10 +31,8 @@ "Alkalmazásinformáció a következőhöz: %1$s" "Alkalmazáspár mentése" "%1$s | %2$s" - - - - + "Ezt az alkalmazáspárt nem támogatja az eszköz" + "Hajtsa ki az eszközt az alkalmazáspár használatához" "Tartsa lenyomva a modult az áthelyezéshez." "Modul áthelyezéséhez koppintson duplán, tartsa nyomva az ujját, vagy használjon egyéni műveleteket." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Folyamatban van a(z) %1$s telepítése, %2$s kész" "A(z) %1$s letöltése, %2$s kész" "A(z) %1$s telepítésre vár" - - + "%1$s archiválva. Koppintson a letöltéshez." "Alkalmazásfrissítés szükséges" "Az ikonhoz tartozó alkalmazás nincs frissítve. A parancsikon újbóli engedélyezéséhez frissítse az alkalmazást, vagy távolítsa ez az ikont." "Frissítés" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index c3461ae591..83a4559c54 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -31,10 +31,8 @@ "Տեղեկություններ %1$s հավելվածի մասին" "Պահել հավելվածների զույգը" "%1$s | %2$s" - - - - + "Հավելվածների զույգը չի աջակցվում այս սարքում" + "Բացեք սարքը՝ այս հավելվածների զույգն օգտագործելու համար" "Հպեք և պահեք՝ վիջեթ տեղափոխելու համար։" "Կրկնակի հպեք և պահեք՝ վիջեթ տեղափոխելու համար, կամ օգտվեք հատուկ գործողություններից։" "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s հավելվածը տեղադրվում է, կատարված է %2$s-ը" "%1$s–ի ներբեռնում (%2$s)" "%1$s-ի տեղադրման սպասում" - - + "%1$s հավելվածն արխիվացված է։ Հպեք՝ ներբեռնելու համար:" "Պահանջվում է թարմացնել հավելվածը" "Հավելվածը հնացել է։ Թարմացրեք այն ձեռքով, որպեսզի շարունակեք օգտագործել դյուրանցումը, կամ հեռացրեք հավելվածի պատկերակը։" "Թարմացնել" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index d2cbca6ef2..edf62a4f62 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -31,10 +31,8 @@ "Info aplikasi untuk %1$s" "Simpan pasangan aplikasi" "%1$s | %2$s" - - - - + "Pasangan aplikasi ini tidak didukung di perangkat ini" + "Buka perangkat untuk menggunakan pasangan aplikasi ini" "Sentuh lama untuk memindahkan widget." "Ketuk dua kali & tahan untuk memindahkan widget atau gunakan tindakan khusus." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s sedang diinstal, %2$s selesai" "%1$s sedang didownload, %2$s selesai" "%1$s menunggu dipasang" - - + "%1$s diarsipkan. Ketuk untuk mendownload." "Aplikasi perlu diupdate" "Aplikasi untuk ikon ini belum diupdate. Anda dapat mengupdate secara manual untuk mengaktifkan kembali pintasan ini, atau hapus ikon." "Update" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 98272cd0f4..b75f61fa13 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -31,10 +31,8 @@ "Upplýsingar um forrit fyrir %1$s" "Vista forritapar" "%1$s | %2$s" - - - - + "Þetta forritapar er ekki stutt í þessu tæki" + "Opnaðu tæki til að nota þetta forritapar" "Haltu fingri á græju til að færa hana." "Ýttu tvisvar og haltu fingri á græju til að færa hana eða notaðu sérsniðnar aðgerðir." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Setur upp %1$s, %2$s lokið" "%1$s í niðurhali, %2$s lokið" "%1$s bíður uppsetningar" - - + "%1$s er í geymslu. Ýttu til að sækja." "Uppfæra þarf forritið" "Forritið fyrir þetta tákn er ekki uppfært. Þú getur uppfært það handvirkt til að kveikja aftur á þessari flýtileið eða fjarlægt táknið." "Uppfæra" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 93a20ea092..0c76ba9680 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -31,10 +31,8 @@ "Informazioni sull\'app %1$s" "Salva coppia di app" "%1$s | %2$s" - - - - + "Questa coppia di app non è supportata su questo dispositivo" + "Apri il dispositivo per usare questa coppia di app" "Tocca e tieni premuto per spostare un widget." "Tocca due volte e tieni premuto per spostare un widget o per usare le azioni personalizzate." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Installazione di %1$s, completamento: %2$s" "Download di %1$s in corso, %2$s completato" "%1$s in attesa di installazione" - - + "App %1$s archiviata. Tocca per scaricare." "È necessario aggiornare l\'app" "L\'app relativa a questa icona non è aggiornata. Puoi eseguire manualmente l\'aggiornamento per riattivare questa scorciatoia oppure rimuovere l\'icona." "Aggiorna" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 6e2b42a0ab..3132e2dc93 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -31,10 +31,8 @@ "‏פרטים על האפליקציה %1$s" "שמירה של צמד אפליקציות" "%1$s | %2$s" - - - - + "צמד האפליקציות הזה לא נתמך במכשיר הזה" + "צריך לפתוח את המכשיר כדי להשתמש בצמד האפליקציות הזה" "להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה." "כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות." "%1$d × %2$d" @@ -117,7 +115,7 @@ "עריכה של מסך הבית" "הגדרות של מסך הבית" "הושבת על ידי מנהל המערכת שלך" - "אישור לסיבוב מסך הבית" + "סיבוב מסך הבית" "כאשר מסובבים את הטלפון" "סימני ההתראות" "מופעל" @@ -137,8 +135,7 @@ "%1$s בתהליך התקנה, %2$s הושלמו" "הורדת %1$s מתבצעת, %2$s הושלמו" "מחכה להתקנה של %1$s" - - + "אפליקציית %1$s הועברה לארכיון. יש להקיש כדי להוריד." "נדרש עדכון לאפליקציה" "האפליקציה של הסמל הזה לא מעודכנת. אפשר לעדכן אותה ידנית כדי להפעיל מחדש את קיצור הדרך הזה, או להסיר את הסמל." "עדכון" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 25c3392270..7f6846cd91 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -31,10 +31,8 @@ "%1$s のアプリ情報" "アプリのペア設定を保存" "%1$s | %2$s" - - - - + "このデバイスは、このアプリのペア設定に対応していません" + "このアプリのペア設定を使用するには、デバイスを開いてください" "長押ししてウィジェットを移動させます。" "ウィジェットをダブルタップして長押ししながら移動するか、カスタム操作を使用してください。" "%1$dx%2$d" @@ -137,8 +135,7 @@ "%1$s をインストールしています: %2$s 完了" "%1$sをダウンロード中、%2$s完了" "%1$sのインストール待ち" - - + "%1$s はアーカイブ済みです。ダウンロードするにはタップします。" "アプリの更新が必要" "このアイコンのアプリは更新されていません。手動で更新して、このショートカットを再度有効にできます。また、アイコンを削除することもできます。" "更新" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index 884e28221c..ae3b1e6414 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -31,10 +31,8 @@ "%1$s-ის აპის ინფო" "აპთა წყვილის შენახვა" "%1$s | %2$s" - - - - + "ამ მოწყობილობაზე აღნიშნული აპთა წყვილი არ არის მხარდაჭერილი" + "გაშალეთ მოწყობილობა ამ აპთა წყვილის გამოსაყენებლად" "შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად." "ორმაგი შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად ან მორგებული მოქმედებების გამოსაყენებლად." "%1$d × %2$d" @@ -137,8 +135,7 @@ "ინსტალირდება %1$s, %2$s დასრულებულია" "მიმდინარეობს %1$s-ის ჩამოტვირთვა, %2$s დასრულდა" "%1$s ელოდება ინსტალაციას" - - + "%1$s დაარქივებულია. შეეხეთ ჩამოსატვირთად." "საჭიროა აპის განახლება" "ამ ხატულის აპი განახლებული არ არის. შეგიძლიათ, ხელით განაახლოთ ამ მალსახმობის ხელახლა გასააქტიურებლად, ან ამოშალოთ ხატულა." "განახლება" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index eb25105469..70384830c4 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -31,10 +31,8 @@ "%1$s қолданбасы туралы ақпарат" "Қолданбаларды жұптау әрекетін сақтау" "%1$s | %2$s" - - - - + "Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды." + "Қолданбаларды жұптау функциясын пайдалану үшін құрылғыны ашыңыз." "Виджетті жылжыту үшін басып тұрыңыз." "Виджетті жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s орнатылуда, %2$s аяқталды" "%1$s жүктелуде, %2$s аяқталды" "%1$s орнату күтілуде" - - + "%1$s мұрағатталды. Жүктеп алу үшін түртіңіз." "Қолданбаны жаңарту қажет" "Осы белгіше үшін қолданба жаңартылмаған. Оны қолмен жаңартып, осы таңбашаны қайта іске қоса аласыз немесе белгішені өшіріп тастаңыз." "Жаңарту" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index fd2cd4eb0e..1297deefbc 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -31,10 +31,8 @@ "ព័ត៌មានកម្មវិធី​សម្រាប់ %1$s" "រក្សាទុកគូកម្មវិធី" "%1$s | %2$s" - - - - + "មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ" + "លាឧបករណ៍ ដើម្បីប្រើគូកម្មវិធីនេះ" "ចុចឱ្យជាប់​ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក​។" "ចុចពីរដង រួចសង្កត់ឱ្យជាប់ ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក ឬប្រើ​សកម្មភាព​តាមបំណង​។" "%1$d × %2$d" @@ -137,8 +135,7 @@ "កំពុង​ដំឡើង %1$s, បាន​បញ្ចប់ %2$s" "កំពុងដោនឡូត %1$s បានបញ្ចប់ %2$s" "%1$s កំពុងរង់ចាំការដំឡើង" - - + "%1$s ត្រូវបានទុក​ក្នុង​បណ្ណសារ។ សូមចុចដើម្បីទាញយក។" "តម្រូវឱ្យមាន​កំណែកម្មវិធីថ្មី" "កម្មវិធីសម្រាប់​រូបតំណាងនេះ​មិនត្រូវបានដំឡើងកំណែ​ទេ។ អ្នកអាច​ដំឡើងកំណែ​ដោយផ្ទាល់ ដើម្បីបើក​ផ្លូវកាត់នេះឡើងវិញ ឬលុបរូបតំណាងនេះ។" "ដំឡើងកំណែ" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index b24a679985..2832941591 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -31,10 +31,8 @@ "%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ" "ಆ್ಯಪ್ ಜೋಡಿ ಉಳಿಸಿ" "%1$s | %2$s" - - - - + "ಈ ಆ್ಯಪ್ ಜೋಡಿಯು ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ" + "ಈ ಆ್ಯಪ್ ಜೋಡಿಯನ್ನು ಬಳಸಲು ಸಾಧನವನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ" "ವಿಜೆಟ್ ಸರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ." "ವಿಜೆಟ್ ಸರಿಸಲು ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಲು ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತಿದೆ, %2$s ಪೂರ್ಣಗೊಂಡಿದೆ" "%1$s ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ, %2$s ಪೂರ್ಣಗೊಂಡಿದೆ" "%1$s ಸ್ಥಾಪಿಸಲು ಕಾಯಲಾಗುತ್ತಿದೆ" - - + "%1$s ಅನ್ನು ಆರ್ಕೈವ್ ಮಾಡಲಾಗಿದೆ. ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ." "ಆ್ಯಪ್ ಅಪ್‌ಡೇಟ್ ಅಗತ್ಯವಿದೆ" "ಈ ಐಕಾನ್‌ಗಾಗಿ ಆ್ಯಪ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ. ಈ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಮರು-ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅಪ್‌ಡೇಟ್ ಮಾಡಬಹುದು ಅಥವಾ ಐಕಾನ್ ಅನ್ನು ತೆಗೆದುಹಾಕಬಹುದು." "ಅಪ್‌ಡೇಟ್ ಮಾಡಿ" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index b64bb151a7..5c1e854ce1 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -31,10 +31,8 @@ "%1$s 앱 정보" "앱 페어링 저장" "%1$s | %2$s" - - - - + "이 앱 페어링은 이 기기에서 지원되지 않습니다" + "이 앱 페어링을 사용하려면 기기를 펼치세요" "길게 터치하여 위젯을 이동하세요." "두 번 탭한 다음 길게 터치하여 위젯을 이동하거나 맞춤 작업을 사용하세요." "%1$d×%2$d" @@ -137,8 +135,7 @@ "%1$s 설치 중, %2$s 완료" "%1$s 다운로드 중, %2$s 완료" "%1$s 설치 대기 중" - - + "%1$s 앱이 보관처리되었습니다. 다운로드하려면 탭하세요." "앱 업데이트 필요" "바로가기 아이콘의 앱이 업데이트되지 않았습니다. 직접 업데이트하여 앱 바로가기를 다시 사용할 수 있도록 하거나 아이콘을 삭제하세요." "업데이트" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index c4fd5fe08b..7c32fe64e0 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -31,10 +31,8 @@ "%1$s колдонмосу жөнүндө маалымат" "Эки колдонмону бир маалда пайдаланууну сактоо" "%1$s | %2$s" - - - - + "Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт" + "Бул эки колдонмону бир маалда пайдалануу үчүн түзмөктү ачыңыз" "Виджетти кое бербей басып туруп жылдырыңыз." "Виджетти жылдыруу үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s орнотулууда, %2$s аткарылды" "%1$s жүктөлүп алынууда, %2$s аяктады" "%1$s орнотулушу күтүлүүдө" - - + "%1$s архивделди. Жүктөп алуу үчүн тийип коюңуз." "Колдонмону жаңыртыңыз" "Бул сүрөтчөнүн колдонмосу жаңыртылган эмес. Ыкчам баскычты кайра иштетүү үчүн аны кол менен жаңыртып же сүрөтчөнү өчүрүп койсоңуз болот." "Жаңыртуу" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index ed4c9ed068..0ff2d4ee3f 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -31,10 +31,8 @@ "ຂໍ້ມູນແອັບສຳລັບ %1$s" "ບັນທຶກຈັບຄູ່ແອັບ" "%1$s | %2$s" - - - - + "ການຈັບຄູ່ແອັບນີ້ບໍ່ຮອງຮັບຢູ່ອຸປະກອນນີ້" + "ກາງອຸປະກອນອອກເພື່ອໃຊ້ການຈັບຄູ່ແອັບນີ້" "ແຕະຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ." "ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ ຫຼື ໃຊ້ຄຳສັ່ງກຳນົດເອງ." "%1$d × %2$d" @@ -137,8 +135,7 @@ "ກຳລັງຕິດຕັ້ງ %1$s, %2$s ສຳເລັດແລ້ວ" "%1$s ກຳ​ລັງ​ດາວ​ໂຫຼດ, %2$s ສຳ​ເລັດ" "%1$s ກຳ​ລັງ​ລໍ​ຖ້າ​ຕິດ​ຕັ້ງ" - - + "%1$s ຖືກເກັບໄວ້ໃນແຟ້ມ. ແຕະເພື່ອດາວໂຫລດ." "ຈຳເປັນຕ້ອງອັບເດດແອັບ" "ບໍ່ໄດ້ອັບເດດແອັບສຳລັບໄອຄອນນີ້. ທ່ານສາມາດອັບເດດເອງໄດ້ເພື່ອເປີດການນຳໃຊ້ທາງລັດນີ້ຄືນໃໝ່ ຫຼື ລຶບໄອຄອນດັ່ງກ່າວອອກ." "ອັບເດດ" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index c014d46960..ef81b96551 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -31,10 +31,8 @@ "Programos „%1$s“ informacija" "Išsaugoti programų porą" "%1$s | %2$s" - - - - + "Ši programų pora šiame įrenginyje nepalaikoma" + "Atlenkite įrenginį, kad galėtumėte naudoti šią programų porą." "Dukart pal. ir palaik., kad perkeltumėte valdiklį." "Dukart palieskite ir palaikykite, kad perkeltumėte valdiklį ar naudotumėte tinkintus veiksmus." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Įdiegiama: „%1$s“; baigta: %2$s" "Atsisiunčiama programa „%1$s“, %2$s baigta" "Laukiama, kol bus įdiegta programa „%1$s“" - - + "„%1$s“ suarchyvuota. Palieskite, kad atsisiųstumėte." "Būtina atnaujinti programą" "Šios piktogramos programa neatnaujinta. Galite patys atnaujinti, kad iš naujo įgalintumėte šį spartųjį klavišą, arba pašalinkite piktogramą." "Atnaujinti" diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 73c21fd5c7..d04afa1661 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -31,10 +31,8 @@ "%1$s: informācija par lietotni" "Saglabāt lietotņu pāri" "%1$s | %2$s" - - - - + "Šis lietotņu pāris netiek atbalstīts šajā ierīcē" + "Atveriet ierīci, lai izmantotu šo lietotņu pāri" "Lai pārvietotu logrīku, pieskarieties un turiet." "Lai pārvietotu logrīku, uz tā veiciet dubultskārienu un turiet. Varat arī veikt pielāgotas darbības." "%1$d × %2$d" @@ -120,7 +118,7 @@ "Atļaut sākuma ekrāna pagriešanu" "Pagriežot tālruni" "Paziņojumu punkti" - "Ieslēgts" + "Ieslēgti" "Izslēgts" "Nepieciešama piekļuve paziņojumiem" "Lai tiktu rādīti paziņojumu punkti, ieslēdziet paziņojumus lietotnei %1$s." @@ -137,8 +135,7 @@ "Notiek lietotnes “%1$s” instalēšana. Norise: %2$s." "Lietotnes %1$s lejupielāde (%2$s pabeigti)" "Notiek %1$s instalēšana" - - + "Lietotne %1$s ir arhivēta. Pieskarieties, lai lejupielādētu." "Lietotne ir jāatjaunina" "Šai ikonai paredzētā lietotne nav atjaunināta. Varat to atjaunināt manuāli, lai atkārtoti iespējotu šo saīsni, vai noņemt ikonu." "Atjaunināt" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 3aa17c7496..184d7cce52 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -31,10 +31,8 @@ "Податоци за апликација за %1$s" "Зачувај го парот апликации" "%1$s | %2$s" - - - - + "Паров апликации не е поддржан на уредов" + "Отворете го уредот за да го користите паров апликации" "Допрете и задржете за да преместите виџет." "Допрете двапати и задржете за да преместите виџет или користете приспособени дејства." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s се инсталира, %2$s завршено" "Се презема %1$s, %2$s завршено" "%1$s чека да се инсталира" - - + "%1$s е архивирана. Допрете за преземање." "Потребно е ажурирање на апликацијата" "Апликацијата за оваа икона не е ажурирана. Може да ажурирате рачно за да повторно се овозможи кратенкава или отстранете ја иконата." "Ажурирај" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index c0cee96786..3952b22ee4 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -31,10 +31,8 @@ "%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ" "ആപ്പ് ജോടി സംരക്ഷിക്കുക" "%1$s | %2$s" - - - - + "ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല" + "ഈ ആപ്പ് ജോടി ഉപയോഗിക്കാൻ ഉപകരണം അൺഫോൾഡ് ചെയ്യുക" "വിജറ്റ് നീക്കാൻ സ്‌പർശിച്ച് പിടിക്കുക." "വിജറ്റ് നീക്കാൻ ഡബിൾ ടാപ്പ് ചെയ്യൂ, ഹോൾഡ് ചെയ്യൂ അല്ലെങ്കിൽ ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കൂ." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു, %2$s പൂർത്തിയായി" "%1$s ഡൗൺലോഡ് ചെയ്യുന്നു, %2$s പൂർത്തിയായി" "ഇൻസ്റ്റാൾ ചെയ്യാൻ %1$s കാക്കുന്നു" - - + "%1$s ആർക്കൈവ് ചെയ്തു. ഡൗൺലോഡ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക." "ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്യേണ്ടതുണ്ട്" "ഈ ഐക്കണിനുള്ള ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്തിട്ടില്ല. ഈ കുറുക്കുവഴി വീണ്ടും പ്രവർത്തനക്ഷമമാക്കാൻ നിങ്ങൾക്ക് നേരിട്ട് അപ്‌ഡേറ്റ് ചെയ്യാം അല്ലെങ്കിൽ ഐക്കൺ നീക്കം ചെയ്യാം." "അപ്ഡേറ്റ് ചെയ്യുക" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 3a66990d53..7a73041abe 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -31,10 +31,8 @@ "%1$s-н аппын мэдээлэл" "Апп хослуулалтыг хадгалах" "%1$s | %2$s" - - - - + "Энэ апп хослуулалтыг уг төхөөрөмж дээр дэмждэггүй" + "Энэ апп хослуулалтыг ашиглахын тулд төхөөрөмжийг дэлгэнэ үү" "Виджетийг зөөх бол хүрээд, удаан дарна уу." "Виджетийг зөөх эсвэл захиалгат үйлдлийг ашиглахын тулд хоёр товшоод, удаан дарна уу." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s-г суулгаж байна. %2$s дууссан" "%1$s-г татаж байна, %2$s татсан" "%1$s нь суулгахыг хүлээж байна" - - + "%1$s-г архивласан. Татахын тулд товшино уу." "Аппын шинэчлэлт шаардлагатай" "Энэ дүрс тэмдгийн аппыг шинэчлээгүй. Та энэ товчлолыг дахин идэвхжүүлэх эсвэл дүрсийг хасахын тулд гараар шинэчлэх боломжтой." "Шинэчлэх" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index a0b0cd0e53..c54f6141bb 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -31,10 +31,8 @@ "%1$s साठी ॲपशी संबंधित माहिती" "ॲपची जोडी सेव्ह करा" "%1$s | %2$s" - - - - + "या ॲपची जोडीला या डिव्हाइसवर सपोर्ट नाही" + "ही ॲपची जोडी वापरण्यासाठी डिव्हाइस अनफोल्ड करा" "विजेट हलवण्यासाठी स्पर्श करा आणि धरून ठेवा." "विजेट हलवण्यासाठी किंवा कस्टम कृती वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s इंस्टॉल करत आहे, %2$s पूर्ण झाले" "%1$s डाउनलोड होत आहे , %2$s पूर्ण झाले" "%1$s इंस्टॉल करण्याची प्रतिक्षा करत आहे" - - + "%1$s संग्रहित केले आहे. डाउनलोड करण्यासाठी टॅप करा." "अ‍ॅप अपडेट करणे आवश्‍यक आहे" "या आयकनसाठी अ‍ॅप अपडेट केलेले नाही. हा शॉटकर्ट पुन्हा सुरू करण्यासाठी तुम्ही मॅन्युअली अपडेट करू शकता किंवा आयकन काढून टाका." "अपडेट करा" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 05b286cb2a..ac7f8ed080 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -31,10 +31,8 @@ "Maklumat apl untuk %1$s" "Simpan gandingan apl" "%1$s | %2$s" - - - - + "Gandingan apl ini tidak disokong pada peranti ini" + "Buka lipatan peranti untuk menggunakan gandingan apl ini" "Sentuh & tahan untuk menggerakkan widget." "Ketik dua kali & tahan untuk menggerakkan widget atau menggunakan tindakan tersuai." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s dipasang, %2$s selesai" "%1$s memuat turun, %2$s selesai" "%1$s menunggu untuk dipasang" - - + "%1$s diarkibkan. Ketik untuk muat turun." "Kemas kini apl diperlukan" "Apl untuk ikon ini tidak dikemas kini. Anda boleh mengemas kini secara manual untuk mendayakan semula pintasan atau mengalih keluar ikon." "Kemas kini" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 38430dfcb3..c3067bb2f5 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -31,10 +31,8 @@ "%1$s အတွက် အက်ပ်အချက်အလက်" "အက်ပ်တွဲချိတ်ခြင်း သိမ်းရန်" "%1$s | %2$s" - - - - + "ဤအက်ပ်တွဲချိတ်ခြင်းကို ဤစက်တွင် ပံ့ပိုးမထားပါ" + "ဤအက်ပ်တွဲချိတ်ခြင်းကို သုံးရန် စက်ကိုဖြန့်ပါ" "ဝိဂျက်ကို ရွှေ့ရန် တို့ပြီး ဖိထားပါ။" "ဝိဂျက်ကို ရွှေ့ရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။" "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ကို ထည့်သွင်းနေသည်၊ %2$s ပြီးပါပြီ" "%1$s ဒေါင်းလုဒ်လုပ်နေသည်၊ %2$s ပြီးပါပြီ" "%1$s ကိုထည့်သွင်းရန်စောင့်နေသည်" - - + "%1$s ကို သိမ်းထားသည်။ ဒေါင်းလုဒ်လုပ်ရန် တို့ပါ။" "အက်ပ်ကို အပ်ဒိတ်လုပ်ရန် လိုအပ်သည်" "ဤသင်္ကေတအတွက် အက်ပ်ကို အပ်ဒိတ်လုပ်မထားပါ။ ဤဖြတ်လမ်းလင့်ခ်ကို ပြန်ဖွင့်ရန် ကိုယ်တိုင်အပ်ဒိတ်လုပ်နိုင်သည် (သို့) သင်္ကေတကို ဖယ်ရှားနိုင်သည်။" "အပ်ဒိတ်လုပ်ရန်" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index d6a640b99a..72ac454fa4 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -31,10 +31,8 @@ "Appinformasjon for %1$s" "Lagre apptilkoblingen" "%1$s | %2$s" - - - - + "Denne apptilkoblingen støttes ikke på denne enheten" + "Åpne enheten for å bruke denne apptilkoblingen" "Trykk og hold for å flytte en modul." "Dobbelttrykk og hold inne for å flytte en modul eller bruke tilpassede handlinger." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s installerer, %2$s er fullført" "Laster ned %1$s, %2$s er fullført" "Venter på å installere %1$s" - - + "%1$s er arkivert. Trykk for å laste den ned." "Appen må oppdateres" "Appen for dette ikonet er ikke oppdatert. Du kan oppdatere manuelt for å aktivere denne snarveien igjen, eller du kan fjerne ikonet." "Oppdater" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 7ecf5974d3..d9b4efd348 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -31,10 +31,8 @@ "%1$s का हकमा एपसम्बन्धी जानकारी" "एपको पेयर सेभ गर्नुहोस्" "%1$s | %2$s" - - - - + "यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन" + "यो एप पेयर प्रयोग गर्न डिभाइस अनफोल्ड गर्नुहोस्" "कुनै विजेट सार्न डबल ट्याप गरेर छोइराख्नुहोस्।" "कुनै विजेट सार्न वा आफ्नो रोजाइका कारबाही प्रयोग गर्न डबल ट्याप गरेर छोइराख्नुहोस्।" "%1$d × %2$d" @@ -119,13 +117,13 @@ "तपाईँको प्रशासकद्वारा असक्षम गरिएको" "होम स्क्रिन रोटेट हुन दिइयोस्" "फोन घुमाउँदा" - "सूचनाको प्रतीक जनाउने थोप्लाहरू" + "नोटिफिकेसन डट" "सक्रिय" "निष्क्रिय" "सूचनासम्बन्धी पहुँच आवश्यक हुन्छ" - "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन %1$s को एपसम्बन्धी सूचनाहरूलाई अन गर्नुहोस्" + "नोटिफिकेसन डट देखाउन %1$s को एपसम्बन्धी सूचनाहरूलाई अन गर्नुहोस्" "सेटिङहरू बदल्नुहोस्" - "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउनुहोस्" + "नोटिफिकेसन डट देखाउनुहोस्" "विकासकर्ताका लागि उपलब्ध विकल्पहरू" "एपका आइकनहरू होम स्क्रिनमा राखियोस्" "नयाँ एपका लागि" @@ -137,8 +135,7 @@ "%1$s इन्स्टल गरिँदै छ, %2$s पूरा भयो" "%1$s डाउनलोड गर्दै, %2$s सम्पन्‍न" "%1$s स्थापना गर्न प्रतीक्षा गर्दै" - - + "%1$s अभिलेखमा राखिएको छ। डाउनलोड गर्न ट्याप गर्नुहोस्।" "एप अपडेट गरिनु पर्छ" "यो आइकनले जनाउने एप अपडेट गरिएको छैन। तपाईं यो सर्टकट फेरि अन गर्न म्यानुअल रूपमा अपडेट गर्न सक्नुहुन्छ वा आइकन नै हटाउनुहोस्।" "अपडेट गर्नुहोस्" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 3f39854933..dd7ddeb5f7 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -31,10 +31,8 @@ "App-info voor %1$s" "App-paar opslaan" "%1$s | %2$s" - - - - + "Dit app-paar wordt niet ondersteund op dit apparaat" + "Vouw het apparaat open om dit app-paar te gebruiken" "Tik en houd vast om een widget te verplaatsen." "Dubbeltik en houd vast om een widget te verplaatsen of aangepaste acties te gebruiken." "%1$d × %2$d" @@ -127,7 +125,7 @@ "Instellingen wijzigen" "Toon meldingsstipjes" "Ontwikkelaarsopties" - "App-iconen toevoegen aan startscherm" + "App-iconen op startscherm" "Voor nieuwe apps" "Onbekend" "Verwijderen" @@ -137,8 +135,7 @@ "%1$s installeren, %2$s voltooid" "%1$s wordt gedownload, %2$s voltooid" "%1$s wacht op installatie" - - + "%1$s is gearchiveerd Tik om te downloaden." "App-update vereist" "De app voor dit icoon is niet geüpdatet. Je kunt handmatig updaten om deze snelkoppeling weer aan te zetten of het icoon verwijderen." "Updaten" @@ -186,7 +183,7 @@ "Filteren" "Mislukt: %1$s" "Privéruimte" - "Privé-apps vergrendeld en verborgen houden" + "Houd privé-apps vergrendeld en verborgen" "Privé" "Instellingen voor privéruimte" "Privéruimte vergrendelen/ontgrendelen" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index 181e01072f..9b71abbeaa 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -31,10 +31,8 @@ "%1$s ପାଇଁ ଆପ ସୂଚନା" "ଆପ ପେୟାର ସେଭ କରନ୍ତୁ" "%1$s | %2$s" - - - - + "ଏହି ଆପ ପେୟାର ଏ ଡିଭାଇସରେ ସମର୍ଥିତ ନୁହେଁ" + "ଏହି ଆପ ପେୟାରକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରନ୍ତୁ" "ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।" "ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।" "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ଇନଷ୍ଟଲ୍ କରାଯାଉଛି, %2$s ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି" "%1$s ଡାଉନଲୋଡ୍‌ ହେଉଛି, %2$s ସମ୍ପୂର୍ଣ୍ଣ" "%1$s ଇନଷ୍ଟଲ୍‌ ହେବାକୁ ଅପେକ୍ଷା କରିଛି" - - + "%1$sକୁ ଆର୍କାଇଭ କରାଯାଇଛି। ଡାଉନଲୋଡ୍ କରିବା ପାଇଁ ଟାପ୍‌ କରନ୍ତୁ।" "ଆପକୁ ଅପଡେଟ କରିବା ଆବଶ୍ୟକ" "ଏହି ଆଇକନ ପାଇଁ ଆପକୁ ଅପଡେଟ କରାଯାଇନାହିଁ। ଏହି ସର୍ଟକଟକୁ ପୁଣି-ସକ୍ଷମ କରିବା ପାଇଁ ଆପଣ ମାନୁଆଲୀ ଅପଡେଟ କରିପାରିବେ କିମ୍ବା ଆଇକନଟିକୁ କାଢ଼ି ଦେଇପାରିବେ।" "ଅପଡେଟ କରନ୍ତୁ" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 3d04230230..7ed539f64b 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -31,10 +31,8 @@ "%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ" "ਐਪ ਜੋੜਾਬੱਧ ਰੱਖਿਅਤ ਕਰੋ" "%1$s | %2$s" - - - - + "ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਦਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਨ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ" + "ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਨੂੰ ਵਰਤਣ ਲਈ ਡੀਵਾਈਸ ਨੂੰ ਅਣਫੋਲਡ ਕਰੋ" "ਕਿਸੇ ਵਿਜੇਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।" "ਵਿਜੇਟ ਲਿਜਾਉਣ ਲਈ ਜਾਂ ਵਿਉਂਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰਕੇ ਦਬਾ ਕੇ ਰੱਖੋ।" "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ਨੂੰ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ, %2$s ਪੂਰਾ ਹੋਇਆ" "%1$s ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, %2$s ਸੰਪੂਰਣ" "%1$s ਸਥਾਪਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ" - - + "%1$s ਪੁਰਾਲੇਖਬੱਧ ਹੈ। ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।" "ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਲੋੜ ਹੈ" "ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰਨ ਜਾਂ ਪ੍ਰਤੀਕ ਨੂੰ ਹਟਾਉਣ ਲਈ ਤੁਸੀਂ ਹੱਥੀਂ ਅੱਪਡੇਟ ਕਰ ਸਕਦੇ ਹੋ।" "ਅੱਪਡੇਟ ਕਰੋ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 6c0b7853a7..e382ba9703 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -31,10 +31,8 @@ "Informacje o aplikacji: %1$s" "Zapisz parę aplikacji" "%1$s | %2$s" - - - - + "Ta para aplikacji nie jest obsługiwana na tym urządzeniu" + "Otwórz urządzenie, aby użyć tej pary aplikacji" "Naciśnij i przytrzymaj, aby przenieść widżet." "Naciśnij dwukrotnie i przytrzymaj, aby przenieść widżet lub użyć działań niestandardowych." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Instaluję aplikację %1$s, postęp: %2$s" "Pobieranie elementu %1$s, ukończono: %2$s" "%1$s oczekuje na instalację" - - + "Aplikacja %1$s jest zarchiwizowana. Kliknij, aby ją pobrać." "Wymagana aktualizacja aplikacji" "Aplikacja z tą ikoną nie jest aktualizowana. Możesz zaktualizować ją ręcznie, aby ponownie uruchomić ten skrót, lub usunąć ikonę." "Aktualizuj" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 18c3ca95e6..da08937739 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -31,10 +31,8 @@ "Informações da app para %1$s" "Guardar par de apps" "%1$s | %2$s" - - - - + "Este par de apps não é suportado neste dispositivo" + "Abra o dispositivo para usar este par de apps" "Toque sem soltar para mover um widget." "Toque duas vezes sem soltar para mover um widget ou utilizar ações personalizadas." "%1$d × %2$d" @@ -137,8 +135,7 @@ "A instalar %1$s, %2$s concluído" "A transferir o %1$s, %2$s concluído" "A aguardar a instalação do %1$s" - - + "A app %1$s está arquivada. Toque para transferir." "Atualização da app necessária" "A app deste ícone não está atualizada. Pode atualizar manualmente para reativar este atalho ou remover o ícone." "Atualizar" @@ -186,7 +183,7 @@ "Filtrar" "Falhou: %1$s" "Espaço privado" - "Mantenha as apps privadas bloqueadas e ocultas" + "Mantém as apps privadas bloqueadas e ocultas" "Privado" "Definições do espaço privado" "Bloquear/desbloquear espaço privado" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 7db0e0dff6..10111aae13 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -31,10 +31,8 @@ "Informações do app %1$s" "Salvar par de apps" "%1$s | %2$s" - - - - + "Este Par de apps não está disponível no dispositivo" + "Abra o dispositivo para usar este Par de apps" "Toque e pressione para mover um widget." "Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Instalando %1$s. %2$s concluído" "Fazendo download de %1$s, %2$s concluído" "Aguardando instalação de %1$s" - - + "O app %1$s está arquivado. Toque para baixar." "Atualização obrigatória do app" "O app desse ícone não está atualizado. Você pode remover o ícone ou atualizar o app manualmente para reativar esse atalho." "Atualizar" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index e7bd42d7a5..9eab793ddb 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -31,10 +31,8 @@ "Informații despre aplicație pentru %1$s" "Salvează perechea de aplicații" "%1$s | %2$s" - - - - + "Perechea de aplicații nu este acceptată pe acest dispozitiv" + "Deschide dispozitivul ca să folosești această pereche de aplicații" "Atinge și ține apăsat pentru a muta un widget." "Atinge de două ori și ține apăsat pentru a muta un widget sau folosește acțiuni personalizate." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s se instalează, %2$s finalizat" "%1$s se descarcă (finalizat %2$s)" "%1$s așteaptă instalarea" - - + "%1$s s-a arhivat. Atinge pentru a descărca." "Este necesară actualizarea aplicației" "Aplicația pentru această pictogramă nu este actualizată. Poți să actualizezi manual ca să reactivezi comanda rapidă sau să elimini pictograma." "Actualizează" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index e944627466..1e8407a915 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -31,10 +31,8 @@ "Сведения о приложении \"%1$s\"" "Сохранить настройки одновременного использования двух приложений" "%1$s | %2$s" - - - - + "Одновременно использовать эти два приложения на устройстве нельзя." + "Чтобы одновременно использовать эти два приложения, разложите устройство." "Чтобы переместить виджет, нажмите на него и удерживайте" "Чтобы использовать специальные действия или перенести виджет, нажмите на него дважды и удерживайте." "%1$d x %2$d" @@ -137,8 +135,7 @@ "Установка приложения \"%1$s\" (выполнено %2$s)" "Скачивается \"%1$s\" (%2$s)" "Ожидание установки \"%1$s\"" - - + "Приложение \"%1$s\" находится в архиве. Нажмите, чтобы скачать" "Обновите приложение" "Эта версия приложения устарела. Обновите его вручную, чтобы снова пользоваться ярлыком, или удалите значок." "Обновить" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index d34c43f7c2..ad5d1586fd 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -31,10 +31,8 @@ "%1$s සඳහා යෙදුම් තතු" "යෙදුම් යුගල සුරකින්න" "%1$s | %2$s" - - - - + "මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි" + "මෙම යෙදුම් යුගලය භාවිතා කිරීමට උපාංගය දිගහරින්න" "විජට් එකක් ගෙන යාමට ස්පර්ශ කර අල්ලා ගෙන සිටින්න." "විජට් එකක් ගෙන යාමට හෝ අභිරුචි ක්‍රියා භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s ස්ථාපනය කරමින්, %2$s සම්පූර්ණයි" "%1$s බාගත කරමින්, %2$s සම්පූර්ණයි" "%1$s ස්ථාපනය කිරීමට බලා සිටිමින්" - - + "%1$s ලේඛනාරක්ෂණය කර ඇත. බාගැනීමට තට්ටු කරන්න" "යෙදුම් යාවත්කාලීනයක් අවශ්‍යයි" "මෙම නිරූපකය සඳහා යෙදුම යාවත්කාලීන කර නැත. ඔබට මෙම කෙටි මඟ යළි සබල කිරීමට හෝ නිරූපකය ඉවත් කිරීමට හස්තීයව යාවත්කාලීන කළ හැකිය." "යාවත්කාලීන කරන්න" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 743a7b4f71..b4b67a1bc4 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -31,10 +31,8 @@ "Informácie o aplikácii pre %1$s" "Uložiť pár aplikácií" "%1$s | %2$s" - - - - + "Tento pár aplikácií nie je v tomto zariadení podporovaný" + "Ak chcete používať tento pár aplikácií, rozložte zariadenie" "Pridržaním presuňte miniaplikáciu." "Dvojitým klepnutím a pridržaním presuňte miniaplikáciu alebo použite vlastné akcie." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Inštaluje sa %1$s. Dokončené: %2$s." "Sťahuje sa aplikácia %1$s. Stiahnuté: %2$s" "Aplikácia %1$s čaká na inštaláciu" - - + "Aplikácia %1$s je archivovaná. Stiahnite klepnutím." "Vyžaduje sa aktualizácia aplikácie" "Aplikácia, ktorú zastupuje táto ikona, nie je aktualizovaná. Môžete ju ručne aktualizovať, aby odkaz znova fungoval, prípadne môžete ikonu odstrániť." "Aktualizovať" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 9051805e2e..9472e44a07 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -31,10 +31,8 @@ "Podatki o aplikaciji za: %1$s" "Shrani par aplikacij" "%1$s | %2$s" - - - - + "Ta par aplikacij ni podprt v tej napravi" + "Razprite napravo, če želite uporabljati ta par aplikacij" "Pridržite pripomoček, da ga premaknete." "Dvakrat se dotaknite pripomočka in ga pridržite, da ga premaknete, ali pa uporabite dejanja po meri." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s se namešča, dokončano: %2$s" "Prenašanje aplikacije %1$s; preneseno %2$s" "Aplikacija %1$s čaka na namestitev" - - + "Aplikacija %1$s je arhivirana. Dotaknite se za prenos." "Zahtevana je posodobitev aplikacije" "Aplikacija za to ikono ni posodobljena. Lahko jo ročno posodobite, da znova omogočite to bližnjico, ali pa odstranite ikono." "Posodobi" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index be2db9caad..bfc6fb3944 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -31,10 +31,8 @@ "Informacioni i aplikacionit për %1$s" "Ruaj çiftin e aplikacioneve" "%1$s | %2$s" - - - - + "Ky çift aplikacionesh nuk mbështetet në këtë pajisje" + "Shpalose pajisjen për të përdorur këtë çift aplikacionesh" "Prek dhe mbaj shtypur një miniaplikacion për ta zhvendosur." "Trokit dy herë dhe mbaje shtypur një miniapliikacion për ta zhvendosur atë ose për të përdorur veprimet e personalizuara." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s po instalohet, %2$s i përfunduar" "%1$s po shkarkohet, %2$s të përfunduara" "%1$s po pret të instalohet" - - + "%1$s është arkivuar. Trokit për të shkarkuar." "Kërkohet përditësimi i aplikacionit" "Aplikacioni për këtë ikonë nuk është përditësuar. Mund ta përditësosh manualisht për të riaktivizuar këtë shkurtore ose hiq ikonën." "Përditëso" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 020d60d69a..270654df30 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -31,10 +31,8 @@ "Информације о апликацији за: %1$s" "Сачувај пар апликација" "%1$s | %2$s" - - - - + "Овај пар апликација није подржан на овом уређају" + "Отворите уређај да бисте користили овај пар апликација" "Додирните и задржите ради померања виџета." "Двапут додирните и задржите да бисте померали виџет или користите прилагођене радње." "%1$d×%2$d" @@ -137,8 +135,7 @@ "%1$s се инсталира, %2$s готово" "%1$s се преузима, завршено је %2$s" "%1$s чека на инсталирање" - - + "Апликација %1$s је архивирана. Додирните да бисте је преузели." "Треба да ажурирате апликацију" "Апликација за ову икону није ажурирана. Можете да је ручно ажурирате да бисте поново омогућили ову пречицу или уклоните икону." "Ажурирај" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 0ab3cfd89a..32c52d8b4c 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -31,10 +31,8 @@ "Appinformation för %1$s" "Spara appar som ska användas tillsammans" "%1$s | %2$s" - - - - + "De här apparna som ska användas tillsammans stöds inte på den här enheten" + "Vik upp enheten för att använda de här apparna som ska användas tillsammans" "Tryck länge för att flytta en widget." "Tryck snabbt två gånger och håll kvar för att flytta en widget eller använda anpassade åtgärder." "%1$d × %2$d" @@ -118,7 +116,7 @@ "Startinställningar" "Inaktiverat av administratören" "Tillåt rotering av startskärmen" - "När mobilen vrids" + "När telefonen vrids" "Aviseringsprickar" "På" "Av" @@ -137,8 +135,7 @@ "%1$s installeras. %2$s har slutförts" "%1$s laddas ned, %2$s klart" "%1$s väntar på installation" - - + "%1$s har arkiverats. Tryck för att ladda ned." "Du måste uppdatera appen" "Appen för den här ikonen har inte uppdaterats. Du kan uppdatera den manuellt för att återaktivera genvägen eller ta bort ikonen." "Uppdatera" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 8bfb82cdfa..193c92ecbc 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -31,10 +31,8 @@ "Maelezo ya programu ya %1$s" "Hifadhi jozi ya programu" "%1$s | %2$s" - - - - + "Jozi hii ya programu haitumiki kwenye kifaa hiki" + "Fungua kifaa ili utumie jozi hii ya programu" "Gusa na ushikilie ili usogeze wijeti." "Gusa mara mbili na ushikilie ili usogeze wijeti au utumie vitendo maalum." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Inasakinisha %1$s, imekamilika %2$s" "%1$s inapakuliwa, %2$s imekamilika" "%1$s inasubiri kusakinisha" - - + "%1$s imewekwa kwenye kumbukumbu. Gusa ili uipakue." "Unahitaji kusasisha programu" "Programu ya aikoni hii haijasasishwa. Unaweza kusasisha mwenyewe ili uruhusu upya njia hii ya mkato au uondoe aikoni." "Sasisha" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index d99f7df860..2f79f4043f 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -31,10 +31,8 @@ "%1$sக்கான ஆப்ஸ் தகவல்கள்" "ஆப்ஸ் ஜோடியைச் சேமி" "%1$s | %2$s" - - - - + "இந்தச் சாதனத்தில் இந்த ஆப்ஸ் ஜோடி ஆதரிக்கப்படவில்லை" + "இந்த ஆப்ஸ் ஜோடியைப் பயன்படுத்த சாதனத்தை விரியுங்கள்" "விட்ஜெட்டை நகர்த்தத் தொட்டுப் பிடிக்கவும்." "விட்ஜெட்டை நகர்த்த இருமுறை தட்டிப் பிடிக்கவும் அல்லது பிரத்தியேகச் செயல்களைப் பயன்படுத்தவும்." "%1$d × %2$d" @@ -127,7 +125,7 @@ "அமைப்புகளை மாற்று" "அறிவிப்புப் புள்ளிகளைக் காட்டு" "டெவெலப்பர் விருப்பங்கள்" - "முகப்புத் திரையில் ஆப்ஸ் ஐகான்களைச் சேர்" + "முகப்புத் திரையில் ஆப்ஸ் ஐகான்களைச் சேர்த்தல்" "புதிய ஆப்ஸை நிறுவும்போது" "தெரியாதது" "அகற்று" @@ -137,8 +135,7 @@ "%1$s நிறுவப்படுகிறது, %2$s முடிந்தது" "%1$sஐப் பதிவிறக்குகிறது, %2$s முடிந்தது" "%1$sஐ நிறுவுவதற்காகக் காத்திருக்கிறது" - - + "%1$s காப்பிடப்பட்டுள்ளது. பதிவிறக்க தட்டுங்கள்." "ஆப்ஸைப் புதுப்பியுங்கள்" "இந்த ஐகானுக்கான ஆப்ஸ் புதுப்பிக்கப்படவில்லை. இந்த ஷார்ட்கட்டை மீண்டும் இயக்கவோ ஐகானை அகற்றவோ நீங்களாகவே புதுப்பிக்கலாம்." "புதுப்பி" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 1dd743b996..5f104e2efe 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -31,10 +31,8 @@ "%1$s కోసం యాప్ సమాచారం" "యాప్ పెయిర్‌ను సేవ్ చేయండి" "%1$s | %2$s" - - - - + "ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు" + "ఈ యాప్ పెయిర్‌ను ఉపయోగించడానికి పరికరాన్ని అన్‌ఫోల్డ్ చేయండి" "విడ్జెట్‌ను తరలించడానికి తాకి & నొక్కి ఉంచండి." "విడ్జెట్‌ను తరలించడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కండి & హోల్డ్ చేయి." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s‌ను ఇన్‌స్టాల్ చేయడం, %2$s పూర్తయింది" "%1$s డౌన్‌లోడ్ అవుతోంది, %2$s పూర్తయింది" "%1$s ఇన్‌స్టాల్ కావడానికి వేచి ఉంది" - - + "%1$s ఆర్కైవ్ చేయబడింది. డౌన్‌లోడ్ చేయడానికి ట్యాప్ చేయండి." "యాప్‌ను అప్‌డేట్ చేయడం అవసరం" "ఈ చిహ్నం కోసం యాప్ అప్‌డేట్ చేయబడలేదు. మీరు ఈ షార్ట్‌కట్‌ను మళ్లీ ఎనేబుల్ చేయడానికి మాన్యువల్‌గా అప్‌డేట్ చేయవచ్చు లేదా చిహ్నాన్ని తీసివేయవచ్చు." "అప్‌డేట్ చేయండి" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 6d21989ed3..c3c2c20f18 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -31,10 +31,8 @@ "ข้อมูลแอปสำหรับ %1$s" "บันทึกคู่แอป" "%1$s | %2$s" - - - - + "ไม่รองรับคู่แอปนี้ในอุปกรณ์เครื่องนี้" + "กางอุปกรณ์เพื่อใช้คู่แอปนี้" "แตะค้างไว้เพื่อย้ายวิดเจ็ต" "แตะสองครั้งค้างไว้เพื่อย้ายวิดเจ็ตหรือใช้การดำเนินการที่กำหนดเอง" "%1$d × %2$d" @@ -137,8 +135,7 @@ "กำลังติดตั้ง %1$s เสร็จแล้ว %2$s" "กำลังดาวน์โหลด %1$s เสร็จแล้ว %2$s" "%1$s กำลังรอติดตั้ง" - - + "เก็บถาวร %1$s แล้ว แตะเพื่อดาวน์โหลด" "ต้องอัปเดตแอป" "แอปสำหรับไอคอนนี้ยังไม่ได้อัปเดต คุณอัปเดตด้วยตนเองได้โดยเปิดใช้ทางลัดนี้อีกครั้งหรือนำไอคอนออก" "อัปเดต" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 7ce7e4a552..8e4dc1dc3d 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -31,10 +31,8 @@ "Impormasyon ng app para sa %1$s" "I-save ang pares ng app" "%1$s | %2$s" - - - - + "Hindi sinusuportahan sa device na ito ang pares ng app na ito" + "I-unfold ang device para magamit ang pares ng app na ito" "Pindutin nang matagal para ilipat ang widget." "I-double tap at pindutin nang matagal para ilipat ang widget o gumamit ng mga custom na pagkilos." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Ini-install ang %1$s, %2$s kumpleto" "Dina-download na ang %1$s, tapos na ang %2$s" "Hinihintay nang mag-install ang %1$s" - - + "Naka-archive ang %1$s. I-tap para i-download." "Kinakailangang i-update ang app" "Hindi updated ang app para sa icon na ito. Puwede kang manual na mag-update para ma-enable ulit ang shortcut na ito, o alisin ang icon." "I-update" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 3dc40bd528..7633940228 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -31,10 +31,8 @@ "%1$s uygulama bilgileri" "Uygulama çiftini kaydedin" "%1$s | %2$s" - - - - + "Bu uygulama çifti bu cihazda desteklenmiyor" + "Bu uygulama çiftini kullanmak için katlanmış durumda olan cihazı açın" "Widget\'ı taşımak için dokunup basılı tutun." "Widget\'ı taşımak veya özel işlemleri kullanmak için iki kez dokunup basılı tutun." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s yükleniyor, %2$s tamamlandı" "%1$s indiriliyor, %2$s tamamlandı" "%1$s uygulaması yüklenmek için bekliyor" - - + "%1$s arşivlendi. İndirmek için dokunun." "Uygulama güncellemesi gerekli" "Bu simgenin uygulaması güncellenmemiş. Simgeyi kaldırabilir ya da uygulamayı manuel olarak güncelleyerek bu kısayolu yeniden etkinleştirebilirsiniz." "Güncelle" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 54824ae87c..7f56e1b151 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -31,10 +31,8 @@ "Інформація про додаток для %1$s" "Зберегти пару додатків" "%1$s | %2$s" - - - - + "Ці два додатки не можна одночасно використовувати на цьому пристрої" + "Розкладіть пристрій, щоб одночасно використовувати ці два додатки" "Натисніть і втримуйте, щоб перемістити віджет." "Двічі натисніть і втримуйте віджет, щоб перемістити його або виконати інші дії." "%1$d × %2$d" @@ -113,7 +111,7 @@ "Папка \"%1$s\", елементів: %2$d" "Папка \"%1$s\", елементів: %2$d або більше" "Одночасне використання двох додатків: %1$s і %2$s" - "Оформлення і стиль" + "Оформлення й стиль" "Редагувати головний екран" "Налаштування головного екрана" "Вимкнув адміністратор" @@ -137,8 +135,7 @@ "%1$s встановлюється, виконано %2$s" "%1$s завантажується, %2$s" "%1$s очікує на завантаження" - - + "Додаток %1$s заархівовано. Натисніть, щоб завантажити." "Потрібно оновити додаток" "Додаток для цього значка не оновлено. Ви можете оновити його вручну, щоб знову ввімкнути цю швидку команду, або можете вилучити значок." "Оновити" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 69ac32d9d7..c945bab555 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -31,10 +31,8 @@ "‏%1$s کے لیے ایپ کی معلومات" "ایپس کے جوڑے کو محفوظ کریں" "%1$s | %2$s" - - - - + "ایپس کا یہ جوڑا اس آلے پر تعاون یافتہ نہیں ہے" + "ایپس کے اس جوڑے کا استعمال کرنے کیلئے آلے کو اَن فولڈ کریں" "ویجیٹ منتقل کرنے کے لیے ٹچ کریں اور پکڑ کر رکھیں۔" "ویجیٹ کو منتقل کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کے لیے دوبار تھپتھپائیں اور پکڑ کر رکھیں۔" "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s انسٹال کی جا رہی ہے، %2$s مکمل ہو گئی" "%1$s ڈاؤن لوڈ ہو رہا ہے، %2$s مکمل ہو گیا" "%1$s انسٹال ہونے کا انتظار کر رہی ہے" - - + "%1$s کو آرکائیو کر لیا گیا ہے۔ ڈاؤن لوڈ کرنے کیلئے تھپتھپائیں۔" "ایپ کی اپ ڈیٹ درکار ہے" "اس آئیکن کیلئے ایپ کو اپ ڈیٹ نہیں کیا گیا ہے۔ آپ اس شارٹ کٹ کو دوبارہ فعال کرنے کے لیے دستی طور پر اپ ڈیٹ کر سکتے ہیں، یا آئیکن کو ہٹا سکتے ہیں۔" "اپ ڈیٹ کریں" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 57e1100ec8..4fbacb7925 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -31,10 +31,8 @@ "%1$s ilovasi axboroti" "Ilova juftini saqlash" "%1$s | %2$s" - - - - + "Bu ilova jufti ushbu qurilmada ishlamaydi" + "Bu ilova juftidan foydalanish uchun qurilmani oching" "Vidjetni bosib turgan holatda suring." "Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning." "%1$d × %2$d" @@ -137,8 +135,7 @@ "%1$s oʻrnatlmoqda, %2$s yakunlandi" "%1$s yuklab olinmoqda, %2$s bajarildi" "%1$s ilovasi o‘rnatilishi kutilmoqda" - - + "%1$s arxivlangan. Yuklab olish uchun bosing." "Ilovani yangilash zarur" "Bu belgi uchun ilova yangilanmagan. Ushbu yorliqni qayta yoqish uchun oddiy usulda yangilashingiz yoki belgini olib tashlashingiz mumkin." "Yangilash" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 06490662cc..290adacca4 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -31,10 +31,8 @@ "Thông tin ứng dụng cho %1$s" "Lưu cặp ứng dụng" "%1$s | %2$s" - - - - + "Cặp ứng dụng này không hoạt động được trên thiết bị này" + "Hãy mở thiết bị để dùng cặp ứng dụng này" "Chạm và giữ để di chuyển một tiện ích." "Nhấn đúp và giữ để di chuyển một tiện ích hoặc sử dụng các thao tác tùy chỉnh." "%1$d × %2$d" @@ -137,8 +135,7 @@ "Đang cài đặt %1$s, hoàn tất %2$s" "Đang tải xuống %1$s, %2$s hoàn tất" "Đang chờ cài đặt %1$s" - - + "Đã lưu trữ %1$s Nhấn để tải xuống." "Cần cập nhật ứng dụng" "Ứng dụng cho biểu tượng này chưa được cập nhật. Bạn có thể cập nhật theo cách thủ công để bật lại phím tắt này hoặc xóa biểu tượng." "Cập nhật" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index b1b238528a..26f42d89be 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -31,10 +31,8 @@ "%1$s 的应用信息" "保存应用对" "%1$s | %2$s" - - - - + "在该设备上无法使用此应用对" + "展开设备即可使用此应用对" "轻触并按住即可移动微件。" "点按两次并按住微件即可移动该微件或使用自定义操作。" "%1$d × %2$d" @@ -137,8 +135,7 @@ "正在安装%1$s,已完成 %2$s" "正在下载%1$s,已完成 %2$s" "%1$s正在等待安装" - - + "已归档“%1$s”。点按即可下载。" "需要更新应用" "此图标对应的应用未更新。您可以手动更新以重新启用该快捷方式,或者移除此图标。" "更新" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 642b14954c..ff71ad26ff 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -31,10 +31,8 @@ "%1$s 的應用程式資料" "儲存應用程式配對" "%1$s | %2$s" - - - - + "此裝置不支援此應用程式配對" + "打開裝置即可使用此應用程式配對" "輕觸並按住即可移動小工具。" "㩒兩下之後㩒住,就可以郁小工具或者用自訂操作。" "%1$d × %2$d" @@ -137,8 +135,7 @@ "正在安裝「%1$s」(已完成 %2$s)" "正在下載 %1$s,已完成 %2$s" "正在等待安裝 %1$s" - - + "「%1$s」已封存。輕按即可下載。" "必須更新應用程式" "你尚未更新這個圖示代表的應用程式。你可以手動更新以重新啟用此快速鍵,或者移除圖示。" "更新" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 4a47f40864..1385fcedbc 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -31,10 +31,8 @@ "「%1$s」的應用程式資訊" "儲存應用程式配對" "%1$s | %2$s" - - - - + "這部裝置不支援這組應用程式配對" + "展開裝置即可使用這組應用程式配對" "按住即可移動小工具。" "輕觸兩下並按住即可移動小工具或使用自訂操作。" "%1$d × %2$d" @@ -137,8 +135,7 @@ "正在安裝「%1$s」(已完成 %2$s)" "正在下載「%1$s」,已完成 %2$s" "正在等待安裝「%1$s」" - - + "已封存「%1$s」。輕觸即可下載。" "必須更新應用程式" "這個圖示代表的應用程式未更新。手動更新即可重新啟用這個捷徑,你也可以移除圖示。" "更新" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 432a19ab8a..8388bb7303 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -31,10 +31,8 @@ "Ulwazi lwe-App ye-%1$s" "Londoloza i-app ebhangqiwe" "%1$s | %2$s" - - - - + "Lokhu kubhanqwa kwe-app akusekelwa kule divayisi" + "Vula idivayisi ukuze usebenzise lokhu kubhanqwa kwe-app" "Thinta uphinde ubambe ukuze uhambise iwijethi." "Thepha kabili uphinde ubambe ukuze uhambise iwijethi noma usebenzise izindlela ezingokwezifiso." "%1$d × %2$d" @@ -137,8 +135,7 @@ "I-%1$s iyafakwa, seyiqede %2$s" "I-%1$s iyalandwa, %2$s kuqediwe" "%1$s ilinde ukufakwa" - - + "I-%1$s ifakwe kungobo yomlando. Thepha ukuze udawunilode." "Kudingeka isibuyekezo se-app" "I-app yalesi sithonjana ibuyekeziwe. Ungabuyekeza mathupha ukuze uphinde unike amandla lesi sinqamuleli, noma ususe isithonjana." "Vuselela" From ad6a49777480eb69540d015fde9dcf0892da8843 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 8 Apr 2024 11:55:29 -0700 Subject: [PATCH 021/143] Import translations. DO NOT MERGE ANYWHERE Bug: 328603775 Auto-generated-cl: translation import (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f481ffe589d4bc647da9c358d1c61471a684f6f0) Merged-In: Ie6ae0a3a4e99f7f7d93e89c17abc5c95de32a83d Change-Id: Ie6ae0a3a4e99f7f7d93e89c17abc5c95de32a83d --- quickstep/res/values-af/strings.xml | 2 +- quickstep/res/values-ar/strings.xml | 6 +++--- quickstep/res/values-b+sr+Latn/strings.xml | 2 +- quickstep/res/values-ca/strings.xml | 2 +- quickstep/res/values-cs/strings.xml | 4 ++-- quickstep/res/values-es-rUS/strings.xml | 2 +- quickstep/res/values-es/strings.xml | 2 +- quickstep/res/values-eu/strings.xml | 2 +- quickstep/res/values-fi/strings.xml | 4 ++-- quickstep/res/values-gl/strings.xml | 2 +- quickstep/res/values-hi/strings.xml | 6 +++--- quickstep/res/values-hu/strings.xml | 2 +- quickstep/res/values-hy/strings.xml | 4 ++-- quickstep/res/values-in/strings.xml | 6 +++--- quickstep/res/values-iw/strings.xml | 2 +- quickstep/res/values-kn/strings.xml | 2 +- quickstep/res/values-ky/strings.xml | 10 +++++----- quickstep/res/values-mk/strings.xml | 4 ++-- quickstep/res/values-my/strings.xml | 2 +- quickstep/res/values-nl/strings.xml | 2 +- quickstep/res/values-pa/strings.xml | 2 +- quickstep/res/values-pt-rPT/strings.xml | 4 ++-- quickstep/res/values-sk/strings.xml | 2 +- quickstep/res/values-sl/strings.xml | 2 +- quickstep/res/values-sr/strings.xml | 2 +- quickstep/res/values-zh-rCN/strings.xml | 2 +- res/values-af/strings.xml | 2 +- res/values-ar/strings.xml | 4 ++-- res/values-as/strings.xml | 4 ++-- res/values-b+sr+Latn/strings.xml | 2 +- res/values-bs/strings.xml | 2 +- res/values-ca/strings.xml | 4 ++-- res/values-cs/strings.xml | 2 +- res/values-de/strings.xml | 2 +- res/values-es-rUS/strings.xml | 2 +- res/values-eu/strings.xml | 2 +- res/values-fr-rCA/strings.xml | 2 +- res/values-fr/strings.xml | 6 +++--- res/values-gl/strings.xml | 4 ++-- res/values-hi/strings.xml | 4 ++-- res/values-hy/strings.xml | 6 +++--- res/values-in/strings.xml | 6 +++--- res/values-is/strings.xml | 4 ++-- res/values-iw/strings.xml | 2 +- res/values-ja/strings.xml | 4 ++-- res/values-kn/strings.xml | 2 +- res/values-ky/strings.xml | 8 ++++---- res/values-mk/strings.xml | 2 +- res/values-mr/strings.xml | 6 +++--- res/values-ms/strings.xml | 4 ++-- res/values-my/strings.xml | 2 +- res/values-ne/strings.xml | 4 ++-- res/values-nl/strings.xml | 4 ++-- res/values-or/strings.xml | 4 ++-- res/values-pl/strings.xml | 2 +- res/values-ru/strings.xml | 2 +- res/values-sr/strings.xml | 2 +- res/values-sv/strings.xml | 2 +- res/values-tl/strings.xml | 2 +- res/values-zh-rCN/strings.xml | 6 +++--- res/values-zh-rTW/strings.xml | 2 +- 61 files changed, 100 insertions(+), 100 deletions(-) diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml index 308b4115e0..ba78a28b56 100644 --- a/quickstep/res/values-af/strings.xml +++ b/quickstep/res/values-af/strings.xml @@ -93,7 +93,7 @@ "toestel" "Stelselnavigasie-instellings" "Deel" - "Skermkiekie" + "Skermskoot" "Verdeel" "Tik op ’n ander app om verdeelde skerm te gebruik" "Kies ’n ander app as jy verdeelde skerm wil gebruik" diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 4ed610f3d2..d25b211a4a 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -21,7 +21,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "تثبيت" "شكل مجاني" - "ليست هناك عناصر تم استخدامها مؤخرًا" + "ما مِن عناصر تم استخدامها مؤخرًا" "إعدادات استخدام التطبيق" "محو الكل" "التطبيقات المستخدمة مؤخرًا" @@ -96,10 +96,10 @@ "لقطة شاشة" "تقسيم" "انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة." - "اختَر تطبيقًا آخر لاستخدام \"وضع تقسيم الشاشة\"." + "اختَر تطبيقًا آخر لاستخدام \"وضع تقسيم الشاشة\"" "إلغاء" "الخروج من وضع تقسيم الشاشة" - "اختَر تطبيقًا آخر لاستخدام \"وضع تقسيم الشاشة\"." + "اختَر تطبيقًا آخر لاستخدام \"وضع تقسيم الشاشة\"" "لا يسمح التطبيق أو لا تسمح مؤسستك بهذا الإجراء." "التطبيقات المصغّرة غير متوفّرة حاليًا، يرجى اختيار تطبيق آخر." "هل تريد تخطي الدليل التوجيهي للتنقّل؟" diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml index ba2cd6a98c..5d7652b63d 100644 --- a/quickstep/res/values-b+sr+Latn/strings.xml +++ b/quickstep/res/values-b+sr+Latn/strings.xml @@ -111,7 +111,7 @@ "Prevucite na stranu da biste koristili 2 aplikacije odjednom" "Sporo prevucite nagore da biste videli traku zadataka" "Dobijajte predloge aplikacija na osnovu rutine" - "Dugo pritiskajte razdelnik da biste zakačili traku zadataka" + "Dugo pritisnite razdelnik da biste zakačili traku zadataka" "Uradite više pomoću trake zadataka" "Uvek prikazuj traku zadataka" "Da bi traka zadataka uvek bila prikazana u dnu ekrana, dodirnite i zadržite razdelnik" diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index 79748e0594..c16b64e909 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -128,7 +128,7 @@ "Es mostra la Barra de tasques" "S\'ha amagat la Barra de tasques" "Barra de navegació" - "Mostra Barra de tasques" + "Barra de tasques sempre visible" "Canvia el mode de navegació" "Separador de la Barra de tasques" "Mou a la part superior o a l\'esquerra" diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index 96c0b4b027..1e58c9c087 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -21,7 +21,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Připnout" "Neomezený režim" - "Žádné nedávné položky" + "Žádné položky z nedávné doby" "Nastavení využití aplikací" "Vymazat vše" "Poslední aplikace" @@ -111,7 +111,7 @@ "Přetáhněte aplikaci na stranu a používejte tak dvě najednou" "Panel aplikací zobrazíte pomalým přejetím prstem nahoru" "Dostávejte návrhy aplikací podle toho, jaké používáte" - "Dlouhým stisknutím oddělovače připnete panel aplikací" + "Dlouhým stisknutím oddělovače panel aplikací připnete" "Více možností s panelem aplikací" "Stálé zobrazení panelu aplikací" "Pokud chcete, aby se panel aplikací vždy zobrazoval ve spodní části obrazovky, podržte oddělovač." diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index 213aff50bb..66cf7b9429 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -128,7 +128,7 @@ "Barra de tareas visible" "Barra de tareas oculta" "Barra de navegación" - "Ver siempre Barra de tareas" + "Barra de tareas visible" "Cambiar el modo de navegación" "Divisor de la Barra de tareas" "Mover a la parte superior o izquierda" diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index 64d01a4db2..0152b84b68 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -128,7 +128,7 @@ "Barra de tareas visible" "Barra de tareas oculta" "Barra de navegación" - "Barra de Tareas visible" + "Barra de tareas visible" "Cambiar el modo de navegación" "Divisor de Barra de Tareas" "Mover arriba/a la izquierda" diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml index 17e4df3a92..4fe02c882b 100644 --- a/quickstep/res/values-eu/strings.xml +++ b/quickstep/res/values-eu/strings.xml @@ -109,7 +109,7 @@ "Biratu pantaila" "Zereginen barra erabiltzeko argibideak" "Bi aplikazio batera erabiltzeko, arrastatu bat albo batera" - "Zereginen barra ikusteko, pasatu hatza gora poliki" + "Zereginen barra ikusteko, pasatu hatza gora mantso" "Jaso aplikazioen iradokizunak erabileran oinarrituta" "Zereginen barra ainguratzeko, sakatu zatitzailea luze" "Egin gauza gehiago zereginen barrarekin" diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml index 5f5701635e..b92ef0522e 100644 --- a/quickstep/res/values-fi/strings.xml +++ b/quickstep/res/values-fi/strings.xml @@ -108,9 +108,9 @@ "Ohita" "Käännä näyttö" "Tehtäväpalkin ohje" - "Vedä sovellus sivuun, ja voit käyttää kahta sovellusta" + "Vedä sovellus sivuun ja käytä kahta sovellusta" "Näytä tehtäväpalkki pyyhkäisemällä ylös hitaasti" - "Sovellussuosituksia käytön perusteella" + "Vastaanota sovellussuosituksia käytön perusteella" "Kiinnitä tehtäväpalkki painamalla jakajaa pitkään" "Vinkkejä tehtäväpalkin tehokkaampaan käyttöön" "Näytä tehtäväpalkki aina" diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml index 8b69179317..2207f17856 100644 --- a/quickstep/res/values-gl/strings.xml +++ b/quickstep/res/values-gl/strings.xml @@ -111,7 +111,7 @@ "Arrastra unha aplicación cara a un lado para usar dúas á vez" "Pasa o dedo amodo cara arriba para ver a barra de tarefas" "Obtén suxestións de aplicacións en función da túa rutina" - "Mantén premida a liña divisoria para fixar a Barra de tarefas" + "Mantén premida a liña divisoria para fixar a barra de tarefas" "Tira máis proveito da barra de tarefas" "Mostrar sempre a barra de tarefas" "Para fixar a barra de tarefas na parte inferior, mantén premida a liña divisoria" diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 1216746a4f..51351cb49f 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -21,9 +21,9 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "पिन करें" "फ़्रीफ़ॉर्म" - "हाल ही में इस्तेमाल किया गया कोई ऐप्लिकेशन नहीं है" + "हाल ही का कोई आइटम नहीं है" "ऐप्लिकेशन इस्तेमाल की सेटिंग" - "सभी ऐप्लिकेशन बंद करें" + "सभी हटाएं" "हाल ही में इस्तेमाल किए गए ऐप्लिकेशन" "टास्क बंद किया गया" "%1$s, %2$s" @@ -109,7 +109,7 @@ "स्क्रीन घुमाएं" "टास्कबार का ट्यूटोरियल" "किसी ऐप को किनारे की ओर ड्रैग करके 2 ऐप एक साथ इस्तेमाल करें" - "टास्कबार दिखाने के लिए, ऊपर की ओर धीरे से स्वाइप करें" + "टास्कबार देखने के लिए, ऊपर की ओर धीरे से स्वाइप करें" "डिवाइस के इस्तेमाल के आधार पर ऐप्लिकेशन के सुझाव पाएं" "टास्कबार को पिन करने के लिए डिवाइडर को दबाकर रखें" "टास्कबार की मदद से कई और काम करें" diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml index ff784c34a4..7ea486d4d2 100644 --- a/quickstep/res/values-hu/strings.xml +++ b/quickstep/res/values-hu/strings.xml @@ -128,7 +128,7 @@ "Feladatsáv megjelenítve" "Feladatsáv elrejtve" "Navigációs sáv" - "Mindig megjelenő feladatsáv" + "Mindig megjelenő Feladatsáv" "Navigációs mód módosítása" "Feladatsáv-elválasztó" "Mozgatás felülre vagy a bal oldalra" diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml index af613a6e9b..367d378724 100644 --- a/quickstep/res/values-hy/strings.xml +++ b/quickstep/res/values-hy/strings.xml @@ -96,10 +96,10 @@ "Սքրինշոթ անել" "Տրոհել" "Հպեք այլ հավելվածի՝ տրոհված էկրանից օգտվելու համար" - "Ընտրեք այլ հավելված՝ կիսված էկրանից օգտվելու համար" + "Ընտրեք այլ հավելված՝ տրոհված էկրանից օգտվելու համար" "Չեղարկել" "Դուրս գալ տրոհված էկրանի ռեժիմից" - "Ընտրեք այլ հավելված՝ կիսված էկրանից օգտվելու համար" + "Ընտրեք այլ հավելված՝ տրոհված էկրանից օգտվելու համար" "Այս գործողությունն արգելված է հավելվածի կամ ձեր կազմակերպության կողմից" "Վիջեթները ներկայումս չեն աջակցվում. ընտրեք այլ հավելված" "Բաց թողնե՞լ նավիգացիայի ուղեցույցը" diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml index 5ced56f194..6208796516 100644 --- a/quickstep/res/values-in/strings.xml +++ b/quickstep/res/values-in/strings.xml @@ -96,10 +96,10 @@ "Screenshot" "Pisahkan" "Ketuk aplikasi lain untuk memakai layar terpisah" - "Pilih aplikasi lain untuk menggunakan layar terpisah" + "Pilih aplikasi lain untuk dibuka di layar terpisah" "Batal" "Keluar dari pemilihan layar terpisah" - "Pilih aplikasi lain untuk memakai layar terpisah" + "Pilih aplikasi lain untuk dibuka di layar terpisah" "Tindakan ini tidak diizinkan oleh aplikasi atau organisasi Anda" "Widget saat ini tidak didukung, pilih aplikasi lain" "Lewati tutorial gestur?" @@ -112,7 +112,7 @@ "Geser perlahan ke atas untuk menampilkan Taskbar" "Dapatkan saran aplikasi berdasarkan rutinitas Anda" "Tekan lama pemisah untuk menyematkan Taskbar" - "Lakukan lebih banyak dengan Taskbar" + "Lakukan lebih banyak hal dengan Taskbar" "Selalu tampilkan Taskbar" "Untuk selalu menampilkan Taskbar di bagian bawah layar Anda, sentuh & tahan pembatasnya" "Tutup" diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml index f862f9ae5b..f84db183f2 100644 --- a/quickstep/res/values-iw/strings.xml +++ b/quickstep/res/values-iw/strings.xml @@ -110,7 +110,7 @@ "הסבר על סרגל האפליקציות" "כדי להשתמש בשתי אפליקציות בו-זמנית, צריך לגרור אפליקציה לצד" "צריך להחליק לאט למעלה כדי להציג את סרגל האפליקציות" - "קבלת הצעות לאפליקציות על סמך השימוש השגרתי שלך" + "אפשר לקבל הצעות לאפליקציות על סמך השימוש השגרתי שלך" "כדי להצמיד את סרגל האפליקציות, לוחצים לחיצה ארוכה על המחיצה" "פעולות נוספות שאפשר לעשות עם סרגל האפליקציות" "תמיד להציג את סרגל האפליקציות" diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml index 023f7b5156..6759404c4e 100644 --- a/quickstep/res/values-kn/strings.xml +++ b/quickstep/res/values-kn/strings.xml @@ -111,7 +111,7 @@ "ಒಂದೇ ಬಾರಿಗೆ 2 ಆ್ಯಪ್‌ಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ ಅನ್ನು ಬದಿಗೆ ಎಳೆಯಿರಿ" "ಟಾಸ್ಕ್‌ಬಾರ್ ಕಾಣುವಂತೆ ಮಾಡಲು ನಿಧಾನವಾಗಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ" "ನಿಮ್ಮ ದಿನಚರಿಯ ಆಧಾರದ ಮೇಲೆ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ" - "ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ಪಿನ್ ಮಾಡಲು ಡಿವೈಡರ್ ಮೇಲೆ ದೀರ್ಘಕಾಲ ಒತ್ತಿರಿ" + "ಟಾಸ್ಕ್‌‌ಬಾರ್ ಅನ್ನು ಪಿನ್ ಮಾಡಲು ಡಿವೈಡರ್ ಮೇಲೆ ದೀರ್ಘಕಾಲ ಒತ್ತಿರಿ" "ಟಾಸ್ಕ್‌ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ" "ಯಾವಾಗಲೂ ಟಾಸ್ಕ್‌ಬಾರ್ ಅನ್ನು ತೋರಿಸಿ" "ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದಲ್ಲಿ ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು, ಡಿವೈಡರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ" diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index c758411e09..9920b028f7 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -108,11 +108,11 @@ "Өткрп жиберүү" "Экранды буруу" "Тапшырмалар тактасы жөнүндө маалымат" - "2 колдонмону бир убакта пайдалануу үчүн капталга сүйрөңүз" + "2 колдонмону бир убакта пайдалануу үчүн капталга сүйрөйсүз" "Тапшырмалар тактасын көрүү үчүн экранды жай өйдө сүрүңүз" - "Программаңыздын негизинде сунушталган колдонмолорду алуу" - "Тапшырмалар панелин кадап коюу үчүн бөлгүчтү коё бербей басып туруңуз" - "Тапшырмалар тактасы менен көбүрөөк нерселерди аткарыңыз" + "Аракеттериңизге негизделген сунуштарды алып турасыз" + "Тапшырмалар тактасын кадап коюу үчүн бөлгүчтү коё бербей басып турасыз" + "Тапшырмалар тактасы менен көбүрөөк иш бүтүрөсүз" "Тапшырмалар панелин ар дайым көрсөтүү" "Тапшырмалар панелин экрандын ылдый жагында ар дайым көрсөтүү үчүн бөлгүчтү коё бербей басыңыз" "Жабуу" @@ -128,7 +128,7 @@ "Тапшырмалар панели көрсөтүлдү" "Тапшырмалар панели жашырылды" "Чабыттоо тилкеси" - "Тапшырмалар панелин ар дайым көрсөтүү" + "Такта ар дайым көрүнсүн" "Өтүү режимин өзгөртүү" "Тапшырмалар панелин бөлгүч" "Жогорку/сол бурчка жылдыруу" diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml index 560c80c0f6..a36f7b5f5c 100644 --- a/quickstep/res/values-mk/strings.xml +++ b/quickstep/res/values-mk/strings.xml @@ -108,8 +108,8 @@ "Прескокни" "Ротирајте го екранот" "Обука за лентата со задачи" - "Повлечете апликација настрана за да користите 2 апликации" - "Полека повлечете нагоре за да се прикаже лентата со задачи" + "Повлечете апликација настрана за да користите 2 апликации одеднаш" + "Полека повлечете нагоре за да се прикаже „Лентата со задачи“" "Добивајте предлози за апликации според вашата рутина" "Притиснете долго на разделникот за да ја закачите „Лентата со задачи“" "Правете сешто со „Лентата со задачи“" diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index d30156e751..e8f2e1fda2 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -128,7 +128,7 @@ "Taskbar ပြထားသည်" "Taskbar ဖျောက်ထားသည်" "လမ်းညွှန်ဘား" - "Taskbar အမြဲပြပါ" + "Taskbar အမြဲပြရန်" "ရွှေ့ကြည့်သည့်မုဒ် ပြောင်းရန်" "လုပ်ဆောင်စရာဘား ပိုင်းခြားစနစ်" "အပေါ်/ဘယ်ဘက်သို့ ရွှေ့ရန်" diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml index aa6654641c..12cadbbefd 100644 --- a/quickstep/res/values-nl/strings.xml +++ b/quickstep/res/values-nl/strings.xml @@ -96,7 +96,7 @@ "Screenshot" "Splitsen" "Tik op nog een app om je scherm te splitsen" - "Kies andere app om gesplitst scherm te gebruiken" + "Kies een andere app om gesplitst scherm te gebruiken" "Annuleren" "Sluit de selectie voor gesplitst scherm" "Kies andere app om gesplitst scherm te gebruiken" diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml index 2888969b03..e467303622 100644 --- a/quickstep/res/values-pa/strings.xml +++ b/quickstep/res/values-pa/strings.xml @@ -21,7 +21,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ਪਿੰਨ ਕਰੋ" "ਫ੍ਰੀਫਾਰਮ" - "ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ" + "ਕੋਈ ਹਾਲੀਆ ਆਈਟਮ ਨਹੀਂ" "ਐਪ ਵਰਤੋਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ" "ਸਭ ਕਲੀਅਰ ਕਰੋ" "ਹਾਲੀਆ ਐਪਾਂ" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index 85fe2fbf61..bacdcf07a7 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -36,7 +36,7 @@ "Aceda facilmente às suas apps mais utilizadas, diretamente no ecrã principal. As sugestões mudam em função das suas rotinas. As apps na última fila passam para o ecrã principal." "Aceda facilmente às suas apps mais utilizadas no ecrã principal. As sugestões mudam em função das suas rotinas. As apps na fila dos favoritos passam para o ecrã principal." "Obter sugestões de apps" - "Não, obrigado" + "Não" "Definições" "As apps mais utilizadas aparecem aqui e mudam em função das rotinas." "Arraste as apps para fora da última fila para ver sugestões de apps." @@ -109,7 +109,7 @@ "Rodar ecrã" "Educação da Barra de tarefas" "Arraste uma app para o lado para usar 2 apps em simultâneo" - "Deslize lentamente para cima para mostrar a Barra de tarefas" + "Deslize lentamente para cima para ver a Barra de tarefas" "Receba sugestões de apps baseadas na sua rotina" "Mantenha o divisor premido para fixar a Barra de tarefas" "Faça mais com a Barra de tarefas" diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml index 22a7c0c298..49acd720ea 100644 --- a/quickstep/res/values-sk/strings.xml +++ b/quickstep/res/values-sk/strings.xml @@ -96,7 +96,7 @@ "Snímka obrazovky" "Rozdeliť" "Obrazovku rozdelíte klepnutím na inú aplikáciu" - "Na použitie rozdelenej obrazovky vyberte inú aplikáciu" + "Na použitie rozdelenej obrazovky vyberte ďalšiu aplikáciu" "Zrušiť" "Ukončite výber rozdelenej obrazovky" "Na použitie rozd. obrazovky vyberte inú aplikáciu" diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml index 9a36faa3bb..9f7a92843a 100644 --- a/quickstep/res/values-sl/strings.xml +++ b/quickstep/res/values-sl/strings.xml @@ -128,7 +128,7 @@ "Opravilna vrstica je prikazana" "Opravilna vrstica je skrita" "Vrstica za krmarjenje" - "Stalen prikaz opravilne vrstice" + "Stalen prikaz oprav. vrstice" "Spreminjanje načina navigacije" "Razdelilnik opravilne vrstice" "Premakni na vrh/levo" diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml index 36b89f6817..a7bce7b365 100644 --- a/quickstep/res/values-sr/strings.xml +++ b/quickstep/res/values-sr/strings.xml @@ -111,7 +111,7 @@ "Превуците на страну да бисте користили 2 апликације одједном" "Споро превуците нагоре да бисте видели траку задатака" "Добијајте предлоге апликација на основу рутине" - "Дуго притискајте разделник да бисте закачили траку задатака" + "Дуго притисните разделник да бисте закачили траку задатака" "Урадите више помоћу траке задатака" "Увек приказуј траку задатака" "Да би трака задатака увек била приказана у дну екрана, додирните и задржите разделник" diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index 62269f0f22..f542c9eca2 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -109,7 +109,7 @@ "旋转屏幕" "任务栏教程" "将一个应用拖到一侧,即可同时使用两个应用" - "缓慢向上滑动即可显示任务栏" + "缓慢上滑即可显示任务栏" "根据您的日常使用习惯获得应用建议" "长按分隔线即可固定任务栏" "体验任务栏的更多功能" diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index 1e1b3f3a3a..262038d202 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -82,7 +82,7 @@ "Lys werkprogramme" "Verwyder" "Deïnstalleer" - "Programinligting" + "Appinligting" "Installeer privaat" "Installeer" "Moenie voorstel nie" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index e1b98fb5c3..618e994b7f 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -29,7 +29,7 @@ "الشاشة الرئيسية" "تقسيم الشاشة" "‏معلومات تطبيق %1$s" - "حفظ إعدادات ميزة \"استخدام تطبيقين في الوقت نفسه\"" + "حفظ استخدام التطبيقين معًا" "%1$s | ‏%2$s" "لا يمكن استخدام هذين التطبيقَين في الوقت نفسه على هذا الجهاز" "افتح الجهاز لاستخدام هذين التطبيقَين في الوقت نفسه" @@ -38,7 +38,7 @@ "%1$d × %2$d" "‏العرض %1$d الطول %2$d" "أداة %1$s" - "انقر مع الاستمرار على التطبيق المصغّر لنقله إلى الشاشة الرئيسية." + "انقر مع الاستمرار على التطبيق المصغّر لنقله إلى الشاشة الرئيسية" "إضافة إلى الشاشة الرئيسية" "تمت إضافة الأداة %1$s إلى الشاشة الرئيسية." "اقتراحات" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index 940e2dbcda..0abdd363c8 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -182,11 +182,11 @@ "আনপজ কৰক" "ফিল্টাৰ" "বিফল: %1$s" - "ব্যক্তিগত স্পে’চ" + "প্ৰাইভেট স্পে\'চ" "ব্যক্তিগত এপ্‌সমূহ লক কৰি লুকুৱাই ৰাখক" "ব্যক্তিগত" "ব্যক্তিগত স্পে’চৰ ছেটিং" - "ব্যক্তিগত স্পে’চ লক/আনলক কৰক" + "প্ৰাইভেট স্পে\'চ লক/আনলক কৰক" "লক কৰক" "ব্যক্তিগত স্পে’চৰ স্থানান্তৰণ" "এপ্‌ ইনষ্টল কৰক" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index b99ec65e39..a3b80a6204 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -82,7 +82,7 @@ "Lista poslovnih aplikacija" "Ukloni" "Deinstaliraj" - "Infor. o aplikaciji" + "Podaci o aplikaciji" "Instaliraj na privatni" "Instaliraj" "Ne predlaži aplikaciju" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 0c4356174d..50f7a2e8e3 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -38,7 +38,7 @@ "%1$d × %2$d" "Širina %1$d, visina %2$d" "Vidžet %1$s" - "Dodirnite i držite vidžet da ga pomjerate po početnom ekranu" + "Dodirnite i zadržite vidžet da ga pomjerate po početnom ekranu" "Dodaj na početni ekran" "Vidžet %1$s je dodan na početni ekran" "Prijedlozi" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 37d8626f9a..6825237134 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -113,7 +113,7 @@ "Parella d\'aplicacions: %1$s i %2$s" "Estil i fons de pantalla" "Edita la pantalla d\'inici" - "Config. pantalla d\'inici" + "Configuració de la pantalla d\'inici" "Desactivada per l\'administrador" "Permet la rotació de la pantalla d\'inici" "En girar el telèfon" @@ -189,7 +189,7 @@ "Bloqueja o desbloqueja Espai privat" "Bloqueja" "Canvia a Espai privat" - "Instal·la aplicacions" + "Instal·la apps" "Instal·la les aplicacions a Espai privat" "Menú addicional" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 2def07ca44..ebc7e20994 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -29,7 +29,7 @@ "Domů" "Rozdělit obrazovku" "Informace o aplikaci %1$s" - "Uložit pár aplikací" + "Uložit dvojici aplikací" "%1$s | %2$s" "Tento pár aplikací není na tomto zařízení podporován" "Pokud chcete použít tento pár aplikací, rozložte zařízení" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 5eff0b058c..8dcb567f1f 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -183,7 +183,7 @@ "Filter" "Fehler: %1$s" "Privates Profil" - "Hier kannst du deine privaten Apps verstecken und sperren" + "Hier kannst du deine privaten Apps verbergen und sperren" "Privat" "Einstellungen für privaten Bereich" "Privaten Bereich sperren/entsperren" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index a7259a2634..dbb109ba66 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -29,7 +29,7 @@ "Pantalla principal" "Pantalla dividida" "Información de la app de %1$s" - "Guardar vinculación de apps" + "Guardar vinculación" "%1$s | %2$s" "No se admite esta vinculación de apps en este dispositivo" "Abre el dispositivo para usar esta vinculación de apps" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index f269c25b8f..047ef0a53b 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -113,7 +113,7 @@ "Aplikazio parea: %1$s eta %2$s" "Horma-papera eta estiloa" "Editatu orri nagusia" - "Orri nagusiaren ezarpenak" + "Orri nagusiko ezarpenak" "Administratzaileak desgaitu du" "Eman orri nagusia biratzeko baimena" "Telefonoa biratzean" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 6ddeeef145..4d7c44312e 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -29,7 +29,7 @@ "Accueil" "Écran divisé" "Renseignements sur l\'appli pour %1$s" - "Enregistrer la paire d\'applications" + "Enr. paire d\'applis" "%1$s | %2$s" "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" "Déplier l\'appareil pour utiliser cette paire d\'applications" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index fdeae1cb0f..f6803053b3 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -118,8 +118,8 @@ "Autoriser la rotation de l\'écran d\'accueil" "Lorsque vous faites pivoter le téléphone" "Pastilles de notification" - "Activé" - "Désactivé" + "Activées" + "Désactivées" "Accès aux notifications requis" "Pour afficher les pastilles de notification, activez les notifications de l\'application %1$s" "Modifier les paramètres" @@ -189,7 +189,7 @@ "Verrouiller/Déverrouiller Espace privé" "Verrouiller" "Transition vers Espace privé" - "Installer des applis" + "Installer applis" "Installer des applis dans l\'espace privé" "Dépassement" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 9388948f47..038821efb0 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -29,7 +29,7 @@ "Inicio" "Pantalla dividida" "Información da aplicación para %1$s" - "Gardar emparellamento de aplicacións" + "Gardar parella de apps" "%1$s | %2$s" "O dispositivo non admite este emparellamento de aplicacións" "Desprega o dispositivo para usar este emparellamento de aplicacións" @@ -82,7 +82,7 @@ "Lista de aplicacións de traballo" "Quitar" "Desinstalar" - "Info. da aplicación" + "Información da app" "Instalar en privado" "Instalar" "Non suxerir aplicación" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index f0431490da..8636ed1880 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -29,7 +29,7 @@ "होम स्क्रीन" "स्प्लिट स्क्रीन" "%1$s के लिए ऐप्लिकेशन की जानकारी" - "साथ में इस्तेमाल किए जा सकने वाले ऐप्लिकेशन की जानकारी सेव करें" + "ऐप पेयर सेव करें" "%1$s | %2$s" "साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन, इस डिवाइस पर काम नहीं कर सकते" "साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन इस्तेमाल करने के लिए डिवाइस को अनफ़ोल्ड करें" @@ -183,7 +183,7 @@ "फ़िल्टर" "पूरा नहीं हुआ: %1$s" "प्राइवेट स्पेस" - "निजी ऐप्लिकेशन, लॉक करें और छिपाकर रखें" + "निजी ऐप्लिकेशन को लॉक करके और छिपाकर रखें" "निजी" "प्राइवेट स्पेस सेटिंग" "प्राइवेट स्पेस को लॉक करें/अनलॉक करें" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 83a4559c54..ef77cd98a5 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -29,7 +29,7 @@ "Հիմնական էկրան" "Տրոհել էկրանը" "Տեղեկություններ %1$s հավելվածի մասին" - "Պահել հավելվածների զույգը" + "Պահել հավելվ. զույգը" "%1$s | %2$s" "Հավելվածների զույգը չի աջակցվում այս սարքում" "Բացեք սարքը՝ այս հավելվածների զույգն օգտագործելու համար" @@ -186,9 +186,9 @@ "Անձնական հավելվածները պահեք կողպված և թաքցված" "Անձնական" "Անձնական տարածքի կարգավորումներ" - "Կողպել/ապակողպել անձնական տարածքը" + "Կողպել/ապակողպել մասնավոր տարածքը" "Կողպում" - "Անցում անձնական տարածք" + "Անցում մասնավոր տարածք" "Հավելվածների տեղադրում" "Հավելվածների տեղադրում անձնական տարածքում" "Լրացուցիչ ընտրացանկ" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index edf62a4f62..0fdae966c1 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -32,7 +32,7 @@ "Simpan pasangan aplikasi" "%1$s | %2$s" "Pasangan aplikasi ini tidak didukung di perangkat ini" - "Buka perangkat untuk menggunakan pasangan aplikasi ini" + "Bentangkan perangkat untuk menggunakan pasangan aplikasi ini" "Sentuh lama untuk memindahkan widget." "Ketuk dua kali & tahan untuk memindahkan widget atau gunakan tindakan khusus." "%1$d × %2$d" @@ -183,13 +183,13 @@ "Filter" "Gagal: %1$s" "Ruang pribadi" - "Tetap kunci dan sembunyikan aplikasi pribadi" + "Kunci dan sembunyikan aplikasi pribadi" "Pribadi" "Setelan Ruang Pribadi" "Kunci/Buka Kunci Ruang Pribadi" "Kunci" "Ruang Pribadi Bertransisi" - "Menginstal aplikasi" + "Instal aplikasi" "Instal aplikasi ke Ruang Pribadi" "Menu tambahan" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index b75f61fa13..51c2e522b5 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -186,10 +186,10 @@ "Haltu einkaforritum læstum og földum" "Lokað" "Stillingar einkarýmis" - "Læsaeinkarými/taka einkarými úr lás" + "Læsa leynirými/taka leynirými úr lás" "Læsa" "Einkarými að breytast" "Setja upp forrit" - "Setja upp forrit í einkarými" + "Setja upp forrit í leynirými" "Yfirflæði" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 3132e2dc93..461a25e54d 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -29,7 +29,7 @@ "בית" "מסך מפוצל" "‏פרטים על האפליקציה %1$s" - "שמירה של צמד אפליקציות" + "שמירת צמד אפליקציות" "%1$s | %2$s" "צמד האפליקציות הזה לא נתמך במכשיר הזה" "צריך לפתוח את המכשיר כדי להשתמש בצמד האפליקציות הזה" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 7f6846cd91..5b3e221001 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -123,7 +123,7 @@ "通知へのアクセス権限が必要" "通知ドットを表示するには、「%1$s」のアプリ通知を ON にしてください" "設定を変更" - "通知ドットの表示" + "通知ドットを表示" "開発者向けオプション" "ホーム画面にアプリのアイコンを追加" "新しいアプリをダウンロードしたときに自動で追加します" @@ -183,7 +183,7 @@ "フィルタ" "失敗: %1$s" "プライベート スペース" - "限定公開アプリをロックして非表示" + "プライベート アプリをロック / 非表示状態に保つ" "プライベート" "プライベート スペースの設定" "プライベート スペースをロック / ロック解除する" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 2832941591..fa9a33243f 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -29,7 +29,7 @@ "ಹೋಮ್" "ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್" "%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ" - "ಆ್ಯಪ್ ಜೋಡಿ ಉಳಿಸಿ" + "ಆ್ಯಪ್ ಪೇರ್ ಸೇವ್ ಮಾಡಿ" "%1$s | %2$s" "ಈ ಆ್ಯಪ್ ಜೋಡಿಯು ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ" "ಈ ಆ್ಯಪ್ ಜೋಡಿಯನ್ನು ಬಳಸಲು ಸಾಧನವನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 7c32fe64e0..4c73a208f6 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -29,7 +29,7 @@ "Башкы экран" "Экранды бөлүү" "%1$s колдонмосу жөнүндө маалымат" - "Эки колдонмону бир маалда пайдаланууну сактоо" + "Колдонмолорду сактап коюу" "%1$s | %2$s" "Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт" "Бул эки колдонмону бир маалда пайдалануу үчүн түзмөктү ачыңыз" @@ -182,11 +182,11 @@ "Улантуу" "Чыпкалоо" "Аткарылган жок: %1$s" - "Жеке чөйрө" + "Жеке мейкиндик" "Жеке колдонмолорду кулпулап жана жашырып коюңуз" "Жеке" - "Жеке чөйрөнүн параметрлери" - "Жеке чөйрөнү кулпулоо/кулпусун ачуу" + "Жеке мейкиндиктин параметрлери" + "Жеке мейкиндикти кулпулоо/кулпусун ачуу" "Кулпулоо" "Жеке чөйрөгө өтүү" "Колдонмолорду орнотуу" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 184d7cce52..6a4dd26f0b 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -189,7 +189,7 @@ "Заклучување/отклучување на „Приватен простор“" "Брава" "Префрлање на „Приватен простор“" - "Инсталирање апликации" + "Инсталирајте апликации" "Инсталирање апликации во „Приватен простор“" "Проширено балонче" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index c54f6141bb..bf83246d56 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -117,7 +117,7 @@ "आपल्या प्रशासकाने अक्षम केले" "होम स्क्रीन फिरवण्‍याची अनुमती द्या" "फोन फिरवला जातो तेव्हा" - "सूचना बिंदू" + "नोटिफिकेशन डॉट" "सुरू" "बंद" "सूचनांच्या अ‍ॅक्सेसची आवश्यकता आहे" @@ -145,8 +145,8 @@ "होम स्क्रीनवर जोडा" "आयटम येथे हलवा" "आयटम मुख्य स्क्रीनवर जोडला" - "आयटम काढला" - "पूर्ववत करा" + "आयटम काढून टाकला" + "पहिल्यासारखे करा" "आयटम हलवा" "%3$s मधील %1$s पंक्ती %2$s स्तंभ यावर हलवा" "%1$s स्थानावर हलवा" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index ac7f8ed080..0f3d20d73a 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -182,8 +182,8 @@ "Nyahjeda" "Tapis" "Gagal: %1$s" - "Ruang peribadi" - "Pastikan apl peribadi kekal dikunci dan disembunyikan" + "Ruang privasi" + "Kunci dan sembunyikan apl peribadi" "Peribadi" "Tetapan Ruang Peribadi" "Kunci/Buka kunci Ruang Peribadi" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index c3067bb2f5..05736a50f3 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -38,7 +38,7 @@ "%1$d × %2$d" "အလျား %1$d နှင့် အမြင့် %2$d" "%1$s ဝိဂျက်" - "ပင်မစာမျက်နှာတွင်ရွှေ့ရန် ဝိဂျက်ကို တို့ထိ၍ ဖိထားပါ" + "ဝိဂျက်ကို တို့ထိ၍ ဖိထားပြီး ပင်မစာမျက်နှာပေါ်တွင် နေရာအမျိုးမျိုးသို့ ရွှေ့နိုင်သည်" "ပင်မစာမျက်နှာတွင် ထည့်ရန်" "%1$s ဝိဂျက်ကို ပင်မစာမျက်နှာတွင် ထည့်လိုက်ပြီ" "အကြံပြုချက်" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index d9b4efd348..246e2947b6 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -78,8 +78,8 @@ "मन पर्ने ट्रे अब कुनै ठाँउ छैन" "एपको सूची" "खोज परिणामहरू" - "व्यक्तिगत अनुप्रयोगहरूको सूची" - "कार्यसम्बन्धी अनुप्रयोगहरूको सूची" + "व्यक्तिगत एपहरूको सूची" + "कार्यसम्बन्धी एपहरूको सूची" "हटाउनुहोस्" "अनइन्स्टल गर्नुहोस्" "एपसम्बन्धी जानकारी" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index dd7ddeb5f7..19600a04bf 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -38,7 +38,7 @@ "%1$d × %2$d" "%1$d breed en %2$d hoog" "Widget %1$s" - "Tik op de widget en houd vast om deze te verplaatsen op het startscherm" + "Houd je vinger op de widget om deze te verplaatsen op het startscherm" "Toevoegen aan startscherm" "Widget %1$s toegevoegd aan startscherm" "Suggesties" @@ -172,7 +172,7 @@ "Werkprofiel" "Werk-apps hebben badges en zijn zichtbaar voor je IT-beheerder" "OK" - "Werk-apps zijn onderbroken" + "Werk-apps zijn gepauzeerd" "Je krijgt geen meldingen van je werk-apps" "Je werk-apps kunnen je geen meldingen sturen, je batterij niet gebruiken en geen toegang krijgen tot je locatie" "Je krijgt geen telefoongesprekken, tekstberichten of meldingen van je werk-apps" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index 9b71abbeaa..44a85ca8e7 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -82,7 +82,7 @@ "କାର୍ଯ୍ୟକାରୀ ଆପ୍‌ ତାଲିକା" "କାଢ଼ି ଦିଅନ୍ତୁ" "ଅନଇନଷ୍ଟଲ କରନ୍ତୁ" - "ଆପ୍‌ ସୂଚନା" + "ଆପ ସୂଚନା" "ପ୍ରାଇଭେଟରେ ଇନଷ୍ଟଲ କର" "ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" "ଆପ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ" @@ -146,7 +146,7 @@ "ଆଇଟମ୍‌କୁ ଏଠାକୁ ଘୁଞ୍ଚାନ୍ତୁ" "ହୋମ ସ୍କ୍ରିନରେ ଆଇଟମ ଯୋଗ କରାଗଲା" "ଆଇଟମକୁ କାଢ଼ି ଦିଆଯାଇଛି" - "ପୂର୍ବବତ୍‍" + "ପୂର୍ବବତ କରନ୍ତୁ" "ଆଇଟମ୍‌ ଘୁଞ୍ଚାନ୍ତୁ" "%3$sରେ ଧାଡି %1$s ସ୍ତମ୍ଭ %2$sକୁ ମୁଭ କରନ୍ତୁ" "%1$s ସ୍ଥିତିକୁ ନିଅନ୍ତୁ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index e382ba9703..b9436026cf 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -123,7 +123,7 @@ "Wymagany jest dostęp do powiadomień" "Aby pokazywać kropki powiadomień, włącz powiadomienia aplikacji %1$s" "Zmień ustawienia" - "Pokaż kropki powiadomień" + "Pokazuj kropki powiadomień" "Opcje programisty" "Dodawaj ikony aplikacji do ekranu głównego" "W przypadku nowych aplikacji" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 1e8407a915..0b429669d5 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -29,7 +29,7 @@ "Главный экран" "Разделить экран" "Сведения о приложении \"%1$s\"" - "Сохранить настройки одновременного использования двух приложений" + "Сохранить приложения" "%1$s | %2$s" "Одновременно использовать эти два приложения на устройстве нельзя." "Чтобы одновременно использовать эти два приложения, разложите устройство." diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 270654df30..03eb6039ca 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -82,7 +82,7 @@ "Листа пословних апликација" "Уклони" "Деинсталирај" - "Инфор. о апликацији" + "Подаци о апликацији" "Инсталирај на приватни" "Инсталирај" "Не предлажи апликацију" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 32c52d8b4c..dab8407bab 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -29,7 +29,7 @@ "Startskärm" "Delad skärm" "Appinformation för %1$s" - "Spara appar som ska användas tillsammans" + "Spara app-par" "%1$s | %2$s" "De här apparna som ska användas tillsammans stöds inte på den här enheten" "Vik upp enheten för att använda de här apparna som ska användas tillsammans" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 8e4dc1dc3d..16c9cb8d64 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -29,7 +29,7 @@ "Home" "Split screen" "Impormasyon ng app para sa %1$s" - "I-save ang pares ng app" + "I-save ang app pair" "%1$s | %2$s" "Hindi sinusuportahan sa device na ito ang pares ng app na ito" "I-unfold ang device para magamit ang pares ng app na ito" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 26f42d89be..4c95167da5 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -29,16 +29,16 @@ "主屏幕" "分屏" "%1$s 的应用信息" - "保存应用对" + "保存应用组合" "%1$s | %2$s" "在该设备上无法使用此应用对" - "展开设备即可使用此应用对" + "展开设备即可使用此应用组合" "轻触并按住即可移动微件。" "点按两次并按住微件即可移动该微件或使用自定义操作。" "%1$d × %2$d" "宽 %1$d,高 %2$d" "“%1$s”微件" - "轻触并按住此微件即可在主屏幕上随意移动它" + "轻触并按住此微件即可在主屏幕上随意移动" "添加到主屏幕" "已将“%1$s”微件添加到主屏幕" "建议" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 1385fcedbc..451efc7bc1 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -38,7 +38,7 @@ "%1$d × %2$d" "寬度為 %1$d,高度為 %2$d" "「%1$s」小工具" - "按住小工具即可將它移到主畫面上的任何位置" + "按住小工具即可拖曳到主畫面的任何位置" "新增至主畫面" "已將「%1$s」小工具新增到主畫面" "建議" From e16a2725d2d0b1ca90ee2002d6f104c3450c49fc Mon Sep 17 00:00:00 2001 From: Brandon Dayauon Date: Tue, 28 May 2024 15:49:58 -0700 Subject: [PATCH 022/143] Create a bug fix flag for the FloatingMaskView. Need to create a bug-fix flag since feature flags can't reach nextfood in time for V. We do this by renaming the current flag. According to https://g3doc.corp.google.com/company/teams/android-core-experiments/trunk-stable/gantry-stages/bug-fix.md?cl=head After a flag declaration has been merged, it's no longer possible to change its purpose. If the purpose of a flag changes over time, simply rename the flag; this will create a new workflow and invalidate the previous workflow. In cases where renaming is not possible, please file a bug for the ACE oncall. Even when re-using the name of a flag for a new purpose, please note that all the progress in the pre-existing workflow will be lost; the new bug-fix workflow will start from scratch. bug: 339850589 Test: Presubmit/locally adb shell device_config put launcher_search com.android.launcher3.private_space_add_floating_mask_view true Flag: ACONFIG com.android.launcher3.private_space_add_floating_mask_view STAGING Change-Id: Iffbc6a93c4ef6bbe121e0c8fb83250174f367b9d --- aconfig/launcher_search.aconfig | 5 ++++- src/com/android/launcher3/allapps/PrivateProfileManager.java | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/aconfig/launcher_search.aconfig b/aconfig/launcher_search.aconfig index b243922a29..b98eee6e32 100644 --- a/aconfig/launcher_search.aconfig +++ b/aconfig/launcher_search.aconfig @@ -45,8 +45,11 @@ flag { flag { - name: "private_space_floating_mask_view" + name: "private_space_add_floating_mask_view" namespace: "launcher_search" description: "This flag enables the floating mask view as part of the Private Space animation. " bug: "339850589" + metadata { + purpose: PURPOSE_BUGFIX + } } diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index 27340a3678..604201ae7f 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -738,7 +738,7 @@ public class PrivateProfileManager extends UserProfileManager { /** Fades out the private space container. */ private ValueAnimator translateFloatingMaskView(boolean animateIn) { - if (!Flags.privateSpaceFloatingMaskView() || mFloatingMaskView == null) { + if (!Flags.privateSpaceAddFloatingMaskView() || mFloatingMaskView == null) { return new ValueAnimator(); } // Translate base on the height amount. Translates out on expand and in on collapse. @@ -849,7 +849,7 @@ public class PrivateProfileManager extends UserProfileManager { } private void attachFloatingMaskView(boolean expand) { - if (!Flags.privateSpaceFloatingMaskView()) { + if (!Flags.privateSpaceAddFloatingMaskView()) { return; } mFloatingMaskView = (FloatingMaskView) mAllApps.getLayoutInflater().inflate( From 3b2a1362726737772b3ac321f8f03f301715983e Mon Sep 17 00:00:00 2001 From: Sihua Ma Date: Wed, 29 May 2024 18:10:27 +0000 Subject: [PATCH 023/143] Run UiThreadTest in LauncherMultivalentJUnit Additionally migrating DisplayControllerTest to multivalent Flag: TEST_ONLY Test: atest NexusLauncherRoboTests Test: SysUI studio Change-Id: I9ff89218947b32f79b39bb0e6dd4beabec3b7369 --- .../src/com/android/launcher3/util/DisplayControllerTest.kt | 3 +-- tests/src/com/android/launcher3/popup/SystemShortcutTest.java | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) rename tests/{ => multivalentTests}/src/com/android/launcher3/util/DisplayControllerTest.kt (98%) diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt similarity index 98% rename from tests/src/com/android/launcher3/util/DisplayControllerTest.kt rename to tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt index 273f0c4491..41effa2f01 100644 --- a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt @@ -27,7 +27,6 @@ import android.view.Display import android.view.Surface import androidx.test.annotation.UiThreadTest import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.launcher3.LauncherPrefs import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING @@ -55,7 +54,7 @@ import org.mockito.stubbing.Answer /** Unit tests for {@link DisplayController} */ @SmallTest -@RunWith(AndroidJUnit4::class) +@RunWith(LauncherMultivalentJUnit::class) class DisplayControllerTest { private val appContext: Context = ApplicationProvider.getApplicationContext() diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java index c663be0fb5..98b6b4b7a8 100644 --- a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java +++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java @@ -49,7 +49,6 @@ import android.platform.test.flag.junit.SetFlagsRule; import android.view.View; import androidx.test.annotation.UiThreadTest; -import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.launcher3.allapps.PrivateProfileManager; @@ -60,6 +59,7 @@ import com.android.launcher3.pm.UserCache; import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext; +import com.android.launcher3.util.LauncherMultivalentJUnit; import com.android.launcher3.util.TestSandboxModelContextWrapper; import com.android.launcher3.util.UserIconInfo; import com.android.launcher3.views.BaseDragLayer; @@ -76,7 +76,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(LauncherMultivalentJUnit.class) public class SystemShortcutTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); private static final UserHandle PRIVATE_HANDLE = new UserHandle(11); From af5a393f883dcf0a6afe1835ff5a7ffb44dd448a Mon Sep 17 00:00:00 2001 From: Ats Jenk Date: Wed, 29 May 2024 16:43:06 -0700 Subject: [PATCH 024/143] Fix bubble position when dragged to dismiss view When moving a bubble to dismiss view, use the drag translation x methods to set the translation x values. When bubble is moved to the dismiss view, the container will animate back to the initial position. And we need to account for this while bubble is in the dismiss view. Bug: 339659499 Flag: com.android.wm.shell.enable_bubble_bar Test: manual, drag bubble to other side and then to dismiss view, observe that bar moves back to original side and bubble is at the center of the dismiss view Change-Id: I4c6e1be2dcd1180d985ceafccfc0f18466549347 --- .../bubbles/BubbleDismissController.java | 3 +- .../taskbar/bubbles/BubbleDragAnimator.java | 22 +------------ .../taskbar/bubbles/BubbleDragController.java | 32 +++++++++++++++++++ .../launcher3/taskbar/bubbles/BubbleView.java | 21 ------------ 4 files changed, 35 insertions(+), 43 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java index 0e6fa3c5e8..a6096e229c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java @@ -169,7 +169,8 @@ public class BubbleDismissController { private void setupMagnetizedObject(@NonNull View magnetizedView) { mMagnetizedObject = new MagnetizedObject<>(mActivity.getApplicationContext(), - magnetizedView, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y) { + magnetizedView, BubbleDragController.DRAG_TRANSLATION_X, + DynamicAnimation.TRANSLATION_Y) { @Override public float getWidth(@NonNull View underlyingObject) { return underlyingObject.getWidth() * underlyingObject.getScaleX(); diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java index 287e9067bf..7aed2d2abe 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java @@ -60,7 +60,6 @@ public class BubbleDragAnimator { private final float mBubbleFocusedScale; private final float mBubbleCapturedScale; private final float mDismissCapturedScale; - private final FloatPropertyCompat mTranslationXProperty; /** * Should be initialised for each dragged view @@ -82,28 +81,9 @@ public class BubbleDragAnimator { if (view instanceof BubbleBarView) { mBubbleFocusedScale = SCALE_BUBBLE_BAR_FOCUSED; mBubbleCapturedScale = mDismissCapturedScale; - mTranslationXProperty = DynamicAnimation.TRANSLATION_X; } else { mBubbleFocusedScale = SCALE_BUBBLE_FOCUSED; mBubbleCapturedScale = SCALE_BUBBLE_CAPTURED; - // Wrap BubbleView.DRAG_TRANSLATION_X as it can't be cast to FloatPropertyCompat - mTranslationXProperty = new FloatPropertyCompat<>( - BubbleView.DRAG_TRANSLATION_X.getName()) { - @Override - public float getValue(View object) { - if (object instanceof BubbleView bubbleView) { - return BubbleView.DRAG_TRANSLATION_X.get(bubbleView); - } - return 0; - } - - @Override - public void setValue(View object, float value) { - if (object instanceof BubbleView bubbleView) { - BubbleView.DRAG_TRANSLATION_X.setValue(bubbleView, value); - } - } - }; } } @@ -140,7 +120,7 @@ public class BubbleDragAnimator { mBubbleAnimator .spring(DynamicAnimation.SCALE_X, 1f) .spring(DynamicAnimation.SCALE_Y, 1f) - .spring(mTranslationXProperty, restingPosition.x, velocity.x, + .spring(BubbleDragController.DRAG_TRANSLATION_X, restingPosition.x, velocity.x, mTranslationConfig) .spring(DynamicAnimation.TRANSLATION_Y, restingPosition.y, velocity.y, mTranslationConfig) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java index e04c1b1020..fbd1b88693 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java @@ -24,6 +24,7 @@ import android.view.ViewConfiguration; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.dynamicanimation.animation.FloatPropertyCompat; import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.wm.shell.common.bubbles.BaseBubblePinController.LocationChangeListener; @@ -38,6 +39,37 @@ import com.android.wm.shell.common.bubbles.BubbleBarLocation; * Restores initial position of dragged view if released outside of the dismiss target. */ public class BubbleDragController { + + /** + * Property to update dragged bubble x-translation value. + *

+ * When applied to {@link BubbleView}, will use set the translation through + * {@link BubbleView#getDragTranslationX()} and {@link BubbleView#setDragTranslationX(float)} + * methods. + *

+ * When applied to {@link BubbleBarView}, will use {@link View#getTranslationX()} and + * {@link View#setTranslationX(float)}. + */ + public static final FloatPropertyCompat DRAG_TRANSLATION_X = new FloatPropertyCompat<>( + "dragTranslationX") { + @Override + public float getValue(View view) { + if (view instanceof BubbleView bubbleView) { + return bubbleView.getDragTranslationX(); + } + return view.getTranslationX(); + } + + @Override + public void setValue(View view, float value) { + if (view instanceof BubbleView bubbleView) { + bubbleView.setDragTranslationX(value); + } else { + view.setTranslationX(value); + } + } + }; + private final TaskbarActivityContext mActivity; private BubbleBarController mBubbleBarController; private BubbleBarViewController mBubbleBarViewController; diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java index 61a6bceca1..2e37dc7695 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java @@ -22,13 +22,11 @@ import android.graphics.Canvas; import android.graphics.Outline; import android.graphics.Rect; import android.util.AttributeSet; -import android.util.FloatProperty; import android.view.LayoutInflater; import android.view.View; import android.view.ViewOutlineProvider; import android.widget.ImageView; -import androidx.annotation.NonNull; import androidx.constraintlayout.widget.ConstraintLayout; import com.android.launcher3.R; @@ -48,25 +46,6 @@ public class BubbleView extends ConstraintLayout { public static final int DEFAULT_PATH_SIZE = 100; - /** - * Property to update drag translation value. - * - * @see BubbleView#getDragTranslationX() - * @see BubbleView#setDragTranslationX(float) - */ - public static final FloatProperty DRAG_TRANSLATION_X = new FloatProperty<>( - "dragTranslationX") { - @Override - public void setValue(@NonNull BubbleView bubbleView, float value) { - bubbleView.setDragTranslationX(value); - } - - @Override - public Float get(BubbleView bubbleView) { - return bubbleView.getDragTranslationX(); - } - }; - /** * Flags that suppress the visibility of the 'new' dot or the app badge, for one reason or * another. If any of these flags are set, the dot will not be shown. From 967dd545955e4fd5fc37543ee21a1aa6408ce75e Mon Sep 17 00:00:00 2001 From: Andrew Cole Date: Fri, 31 May 2024 14:45:55 -0700 Subject: [PATCH 025/143] First Unit Tests for Utilities.java Writing some initial unit tests for Utilities.java to get others started so they can easily add to the party. Bug: 297950111 Test: Self Flag: TEST_ONLY Change-Id: I3323e6483790e2c2fbbd5c8db0281802abf0749b --- .../com/android/launcher3/UtilitiesTest.kt | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt diff --git a/tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt b/tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt new file mode 100644 index 0000000000..60a4197c99 --- /dev/null +++ b/tests/multivalentTests/src/com/android/launcher3/UtilitiesTest.kt @@ -0,0 +1,97 @@ +/* + * 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 + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import androidx.test.core.app.ApplicationProvider.getApplicationContext +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.launcher3.util.ActivityContextWrapper +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class UtilitiesTest { + + private lateinit var mContext: Context + + @Before + fun setUp() { + mContext = ActivityContextWrapper(getApplicationContext()) + } + + @Test + fun testIsPropertyEnabled() { + // This assumes the property "propertyName" is not enabled by default + assertFalse(Utilities.isPropertyEnabled("propertyName")) + } + + @Test + fun testGetDescendantCoordRelativeToAncestor() { + val ancestor = + object : ViewGroup(mContext) { + override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {} + } + val descendant = View(mContext) + + descendant.x = 50f + descendant.y = 30f + descendant.scaleX = 2f + descendant.scaleY = 2f + + ancestor.addView(descendant) + + val coord = floatArrayOf(10f, 15f) + val scale = + Utilities.getDescendantCoordRelativeToAncestor(descendant, ancestor, coord, false) + + assertEquals(2f, scale) // Expecting scale to be 2f + assertEquals(70f, coord[0]) + assertEquals(60f, coord[1]) + } + + @Test + fun testRoundArray() { + val floatArray = floatArrayOf(1.2f, 3.7f, 5.5f) + val intArray = IntArray(3) + Utilities.roundArray(floatArray, intArray) + assertArrayEquals(intArrayOf(1, 4, 6), intArray) + } + + @Test + fun testOffsetPoints() { + val points = floatArrayOf(1f, 2f, 3f, 4f) + Utilities.offsetPoints(points, 5f, 6f) + + val expected = listOf(6f, 8f, 8f, 10f) + assertEquals(expected, points.toList()) + } + + @Test + fun testPointInView() { + val view = View(mContext) + view.layout(0, 0, 100, 100) + + assertTrue(Utilities.pointInView(view, 50f, 50f, 0f)) // Inside view + assertFalse(Utilities.pointInView(view, -10f, -10f, 0f)) // Outside view + assertTrue(Utilities.pointInView(view, -5f, -5f, 10f)) // Inside slop + assertFalse(Utilities.pointInView(view, 115f, 115f, 10f)) // Outside slop + } +} From 736527a127f7a6cd93d91a81befc1571c1145774 Mon Sep 17 00:00:00 2001 From: Brandon Dayauon Date: Wed, 22 May 2024 16:12:04 -0700 Subject: [PATCH 026/143] Make PrivateSpaceSettingsButton instead of having just the imageView. This way we can keep the click listener in this PrivateSpaceSettingsButton.java class. - Moved itemInfo creation to PrivateSpaceSettingsButton and created a test class bug: 341053089 Test: manually - presubmit video: https://drive.google.com/file/d/1_TCGrILvwmMpxbgIcbOcpB2AxeBJbyNf/view?usp=sharing Flag: Aconfig com.android.launcher3.enable_private_space Nextfood Change-Id: I79cd319274f4445dd00bc257be81728360d09684 --- res/layout/private_space_header.xml | 2 +- .../allapps/PrivateProfileManager.java | 35 +------- .../allapps/PrivateSpaceSettingsButton.java | 81 +++++++++++++++++++ .../allapps/PrivateProfileManagerTest.java | 2 +- .../PrivateSpaceSettingsButtonTest.java | 56 +++++++++++++ 5 files changed, 141 insertions(+), 35 deletions(-) create mode 100644 src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java create mode 100644 tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java diff --git a/res/layout/private_space_header.xml b/res/layout/private_space_header.xml index cefe39430b..9c0f129b12 100644 --- a/res/layout/private_space_header.xml +++ b/res/layout/private_space_header.xml @@ -37,7 +37,7 @@ android:gravity="center_vertical" android:layout_alignParentEnd="true" android:animateLayoutChanges="false"> - { - logEvents(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP); - openPrivateSpaceSettings(view); - }); } else { settingsButton.setVisibility(GONE); } diff --git a/src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java b/src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java new file mode 100644 index 0000000000..43e42ff8b4 --- /dev/null +++ b/src/com/android/launcher3/allapps/PrivateSpaceSettingsButton.java @@ -0,0 +1,81 @@ +/* + * 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.allapps; + +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP; + +import android.content.Context; +import android.content.Intent; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageButton; + +import com.android.launcher3.logging.StatsLogManager; +import com.android.launcher3.model.data.AppInfo; +import com.android.launcher3.util.ApiWrapper; +import com.android.launcher3.views.ActivityContext; + +public class PrivateSpaceSettingsButton extends ImageButton implements View.OnClickListener { + + private final ActivityContext mActivityContext; + private final StatsLogManager mStatsLogManager; + private final Intent mPrivateSpaceSettingsIntent; + + public PrivateSpaceSettingsButton(Context context) { + this(context, null, 0); + } + + public PrivateSpaceSettingsButton(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PrivateSpaceSettingsButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mActivityContext = ActivityContext.lookupContext(context); + mStatsLogManager = mActivityContext.getStatsLogManager(); + mPrivateSpaceSettingsIntent = + ApiWrapper.INSTANCE.get(context).getPrivateSpaceSettingsIntent(); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + setOnClickListener(this); + } + + @Override + public void onClick(View view) { + mStatsLogManager.logger().log(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP); + AppInfo privateSpaceSettingsItemInfo = createPrivateSpaceSettingsAppInfo(); + view.setTag(privateSpaceSettingsItemInfo); + mActivityContext.startActivitySafely( + view, + mPrivateSpaceSettingsIntent, + privateSpaceSettingsItemInfo); + } + + AppInfo createPrivateSpaceSettingsAppInfo() { + AppInfo itemInfo = new AppInfo(); + itemInfo.id = CONTAINER_PRIVATESPACE; + if (mPrivateSpaceSettingsIntent != null) { + itemInfo.componentName = mPrivateSpaceSettingsIntent.getComponent(); + } + itemInfo.container = CONTAINER_PRIVATESPACE; + return itemInfo; + } +} diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java index 5c50e9788b..6ce1cb71fc 100644 --- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java +++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java @@ -208,7 +208,7 @@ public class PrivateProfileManagerTest { ArgumentCaptor acIntent = ArgumentCaptor.forClass(Intent.class); mPrivateProfileManager.setPrivateSpaceSettingsAvailable(true); - mPrivateProfileManager.openPrivateSpaceSettings(null); + mContext.startActivity(expectedIntent); Mockito.verify(mContext).startActivity(acIntent.capture()); assertEquals("Intent Action is different", diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java new file mode 100644 index 0000000000..9537e1c63f --- /dev/null +++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceSettingsButtonTest.java @@ -0,0 +1,56 @@ +/* + * 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.allapps; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; + +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.launcher3.model.data.AppInfo; +import com.android.launcher3.util.ActivityContextWrapper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class PrivateSpaceSettingsButtonTest { + + private PrivateSpaceSettingsButton mVut; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + Context context = new ActivityContextWrapper(getApplicationContext()); + mVut = new PrivateSpaceSettingsButton(context); + } + + @Test + public void privateSpaceSettingsAppInfo_hasCorrectIdAndContainer() { + AppInfo appInfo = mVut.createPrivateSpaceSettingsAppInfo(); + + assertThat(appInfo.id).isEqualTo(CONTAINER_PRIVATESPACE); + assertThat(appInfo.container).isEqualTo(CONTAINER_PRIVATESPACE); + } +} From 282cdebd0c507521cc1815985e3433c0fad2ec7d Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Sun, 2 Jun 2024 18:54:23 -0700 Subject: [PATCH 027/143] Crop the center when no source rect hint When there is no source rect hint, forge a crop that matches the given aspect ratio and centered, therefore we can use a consolidated animation path and fix the issue with the round corner, which was inproperly scaled in the past. Flag: NONE bug fix Bug: 298409662 Test: Test the overlay in both gesture and button navigation mode,\ with both YouTube and Google Maps,\ in both folded and unfolded mode. Change-Id: I8ae48b999159a51eda2ff41c49cdb3c4e1541176 --- .../util/SwipePipToHomeAnimator.java | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java index 99f10a75db..b13e52d4fa 100644 --- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java +++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java @@ -154,8 +154,23 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { } if (sourceRectHint.isEmpty()) { - mSourceRectHint.setEmpty(); - mSourceHintRectInsets = null; + // Crop a Rect matches the aspect ratio and pivots at the center point. + // To make the animation path simplified. + final float aspectRatio = destinationBounds.width() + / (float) destinationBounds.height(); + if ((appBounds.width() / (float) appBounds.height()) > aspectRatio) { + // use the full height. + mSourceRectHint.set(0, 0, + (int) (appBounds.height() * aspectRatio), appBounds.height()); + mSourceRectHint.offset( + (appBounds.width() - mSourceRectHint.width()) / 2, 0); + } else { + // use the full width. + mSourceRectHint.set(0, 0, + appBounds.width(), (int) (appBounds.width() / aspectRatio)); + mSourceRectHint.offset( + 0, (appBounds.height() - mSourceRectHint.height()) / 2); + } // Create a new overlay layer. We do not call detach on this instance, it's propagated // to other classes like PipTaskOrganizer / RecentsAnimationController to complete @@ -168,11 +183,11 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { Log.d(TAG, getContentOverlay() + " is created: " + reasonForCreateOverlay); } else { mSourceRectHint.set(sourceRectHint); - mSourceHintRectInsets = new Rect(sourceRectHint.left - appBounds.left, - sourceRectHint.top - appBounds.top, - appBounds.right - sourceRectHint.right, - appBounds.bottom - sourceRectHint.bottom); } + mSourceHintRectInsets = new Rect(mSourceRectHint.left - appBounds.left, + mSourceRectHint.top - appBounds.top, + appBounds.right - mSourceRectHint.right, + appBounds.bottom - mSourceRectHint.bottom); addAnimatorListener(new AnimationSuccessListener() { @Override @@ -217,27 +232,7 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { if (mPipContentOverlay != null) { mPipContentOverlay.onAnimationUpdate(tx, mCurrentBounds, progress); } - final PictureInPictureSurfaceTransaction op; - if (mSourceHintRectInsets == null) { - // no source rect hint been set, directly scale the window down - op = onAnimationScale(progress, tx, mCurrentBounds); - } else { - // scale and crop according to the source rect hint - op = onAnimationScaleAndCrop(progress, tx, mCurrentBounds); - } - return op; - } - - /** scale the window directly with no source rect hint being set */ - private PictureInPictureSurfaceTransaction onAnimationScale( - float progress, SurfaceControl.Transaction tx, Rect bounds) { - if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) { - final RotatedPosition rotatedPosition = getRotatedPosition(progress); - return mSurfaceTransactionHelper.scale(tx, mLeash, mAppBounds, bounds, - rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY); - } else { - return mSurfaceTransactionHelper.scale(tx, mLeash, mAppBounds, bounds); - } + return onAnimationScaleAndCrop(progress, tx, mCurrentBounds); } /** scale and crop the window with source rect hint */ From 684ee34fe77d7ae476e22190182c72fca898fae5 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Mon, 3 Jun 2024 10:59:57 +0800 Subject: [PATCH 028/143] Send source rect hint to Shell via stopSwipePipToHome Launcher has calculated it, so shell side can use it directly to avoid inconsistency. Bug: 331315278 Test: Assume the target app support auto-pip and it doesn't draw under display cutout. E.g. LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES Enter PiP from 90 degrees to home with 0 degrees. The left side of pip should not flicker. Change-Id: Id09efc8a30eeef14a031d9db2ab1e00b6f3034bc --- quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java | 3 ++- quickstep/src/com/android/quickstep/SystemUiProxy.java | 4 ++-- .../com/android/quickstep/util/SwipePipToHomeAnimator.java | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 463222dfd0..3199076547 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1614,7 +1614,8 @@ public abstract class AbsSwipeUpHandler Date: Mon, 3 Jun 2024 12:19:35 +0100 Subject: [PATCH 029/143] Handle uiMode changes in QuickstepLauncher - Added uiMode in handled configChanges for QuickstepLauncher, NexusLauncherActivity and RecentsActivity - This avoids Launcher from being recreated when swithching from an app in driving mode (e.g. Maps), which causes massive jank - Launcher layout is affected when driving mode changes, so a recreation is ujnnecessary - Light/dark mode changes still causes Launcher to create as expected Fix: 339747262 Test: Swtich from driving mode app to another or home in 1p and 3p laucnher Test: Switch light/dark mode and Launcher is updated correctly Flag: EXEMPT bugfix Change-Id: I3d52f0625b580a5b5a1ddbbb487c271a4bb0152b --- quickstep/AndroidManifest-launcher.xml | 2 +- quickstep/AndroidManifest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml index c6e2d8cb74..80d8154ba1 100644 --- a/quickstep/AndroidManifest-launcher.xml +++ b/quickstep/AndroidManifest-launcher.xml @@ -48,7 +48,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index bf198b605f..4abf6e150b 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -80,7 +80,7 @@ android:stateNotNeeded="true" android:theme="@style/LauncherTheme" android:screenOrientation="behind" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:enableOnBackInvokedCallback="false" From 050ff39fe23c5b9677da0fe95c3e0a2689019073 Mon Sep 17 00:00:00 2001 From: Uwais Ashraf Date: Mon, 3 Jun 2024 15:35:13 +0000 Subject: [PATCH 030/143] Revert flaky FolderNameProviderTest Bug: 325088328 Test: Presubmit passes Flag: EXEMPT test-only Change-Id: I22c0bfdea32f552ffdb5dacc34038f7b1c668762 --- .../src/com/android/launcher3/folder/FolderNameProviderTest.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{multivalentTests => }/src/com/android/launcher3/folder/FolderNameProviderTest.java (100%) diff --git a/tests/multivalentTests/src/com/android/launcher3/folder/FolderNameProviderTest.java b/tests/src/com/android/launcher3/folder/FolderNameProviderTest.java similarity index 100% rename from tests/multivalentTests/src/com/android/launcher3/folder/FolderNameProviderTest.java rename to tests/src/com/android/launcher3/folder/FolderNameProviderTest.java From 43592a83c8ed95a33f7c07d238c5322044d027e4 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Mon, 3 Jun 2024 12:01:15 -0400 Subject: [PATCH 031/143] Clean up unused debug logs for b/319168409 Flag: NONE removing debug logs Fixes: 319168409 Test: TaplDragTest#testDragAppIcon Change-Id: I73208b042248df04281d52eaf3ed6832abbfc144 --- src/com/android/launcher3/Launcher.java | 8 -------- .../android/launcher3/testing/shared/TestProtocol.java | 1 - 2 files changed, 9 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index b89d05e808..009d7099ca 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -96,9 +96,7 @@ import static com.android.launcher3.popup.SystemShortcut.INSTALL; import static com.android.launcher3.popup.SystemShortcut.WIDGETS; import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK; import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; -import static com.android.launcher3.testing.shared.TestProtocol.CLOCK_ICON_DRAWABLE_LEAKING; import static com.android.launcher3.testing.shared.TestProtocol.LAUNCHER_ACTIVITY_STOPPED_MESSAGE; -import static com.android.launcher3.testing.shared.TestProtocol.testLogD; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.ItemInfoMatcher.forFolderMatch; import static com.android.launcher3.util.SettingsCache.TOUCHPAD_NATURAL_SCROLLING; @@ -423,7 +421,6 @@ public class Launcher extends StatefulActivity @Override @TargetApi(Build.VERSION_CODES.S) protected void onCreate(Bundle savedInstanceState) { - testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onCreate: instance=" + this); mStartupLatencyLogger = createStartupLatencyLogger( sIsNewProcess ? LockedUserState.get(this).isUserUnlockedAtLauncherStartup() @@ -1082,7 +1079,6 @@ public class Launcher extends StatefulActivity @Override protected void onStart() { - testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onStart: instance=" + this); TraceHelper.INSTANCE.beginSection(ON_START_EVT); super.onStart(); if (!mDeferOverlayCallbacks) { @@ -1096,7 +1092,6 @@ public class Launcher extends StatefulActivity @Override @CallSuper protected void onDeferredResumed() { - testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onDeferredResumed: instance=" + this); logStopAndResume(true /* isResume */); // Process any items that were added while Launcher was away. @@ -1284,7 +1279,6 @@ public class Launcher extends StatefulActivity @Override protected void onResume() { - testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onResume: instance=" + this); TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT); super.onResume(); @@ -1300,7 +1294,6 @@ public class Launcher extends StatefulActivity @Override protected void onPause() { - testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onPause: instance=" + this); // Ensure that items added to Launcher are queued until Launcher returns ItemInstallQueue.INSTANCE.get(this).pauseModelPush(FLAG_ACTIVITY_PAUSED); @@ -1783,7 +1776,6 @@ public class Launcher extends StatefulActivity @Override public void onDestroy() { - testLogD(CLOCK_ICON_DRAWABLE_LEAKING, "onDestroy: instance=" + this); super.onDestroy(); ACTIVITY_TRACKER.onActivityDestroyed(this); diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java index c3b7a2af4f..2dfd5a2eb2 100644 --- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java +++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java @@ -175,7 +175,6 @@ public final class TestProtocol { public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466"; public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890"; public static final String OVERVIEW_SELECT_TOOLTIP_MISALIGNED = "b/332485341"; - public static final String CLOCK_ICON_DRAWABLE_LEAKING = "b/319168409"; public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview"; public static final String REQUEST_FLAG_ENABLE_APP_PAIRS = "enable-app-pairs"; From 38478e74f91bae2e3cb519eef98a651ad02fd7c0 Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Fri, 31 May 2024 11:43:55 -0700 Subject: [PATCH 032/143] Make Taskbar Divider PopUp Menu Width Dynamic Test: Manual Bug: 327647761 Flag: com.android.launcher3.enable_taskbar_pinning Change-Id: Ib5c13324afee46b45b2c71e3af86c15a6384a278 --- quickstep/res/layout/taskbar_divider_popup_menu.xml | 5 +++-- .../com/android/launcher3/taskbar/TaskbarDividerPopupView.kt | 4 +--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/quickstep/res/layout/taskbar_divider_popup_menu.xml b/quickstep/res/layout/taskbar_divider_popup_menu.xml index 7f4f76c1e9..676da15828 100644 --- a/quickstep/res/layout/taskbar_divider_popup_menu.xml +++ b/quickstep/res/layout/taskbar_divider_popup_menu.xml @@ -16,8 +16,9 @@ --> @@ -55,10 +56,10 @@ android:gravity="start|center_vertical" android:textAlignment="viewStart" android:paddingStart="12dp" + android:switchPadding="12dp" android:layout_weight="1" android:fontFamily="@*android:string/config_bodyFontFamilyMedium" android:lines="1" - android:ellipsize="end" android:textSize="14sp" android:textColor="?android:attr/textColorPrimary" android:text="@string/always_show_taskbar" /> diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt index 12f1e638c2..10103d8f9d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt @@ -69,8 +69,6 @@ constructor( private lateinit var dividerView: View - private val menuWidth = - resources.getDimensionPixelSize(R.dimen.taskbar_pinning_popup_menu_width) private val popupCornerRadius = Themes.getDialogCornerRadius(context) private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width) private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height) @@ -125,7 +123,7 @@ constructor( /** Orient object as usual and then center object horizontally. */ override fun orientAboutObject() { super.orientAboutObject() - x = mTempRect.centerX() - menuWidth / 2f + x = mTempRect.centerX() - measuredWidth / 2f } override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean { From 273f9ec4873b208d532ded1ff34ed0b5f915849e Mon Sep 17 00:00:00 2001 From: Liran Binyamin Date: Fri, 31 May 2024 10:42:59 -0400 Subject: [PATCH 033/143] Fix bubble bar and handle visibility on first bubble When the animation of the first bubble is suppressed, immediately stash or show the bubble bar to make sure it has been initialized correctly. Also we no longer automatically update the bubble bar visibility based on its alpha value, since we're managing alpha and visibility ourselves. Flag: com.android.wm.shell.enable_bubble_bar Fixes: 343505267 Fixes: 343502240 Test: manually verified state for the following scenarios for the first bubble - in app when keyboard is open - in app -> open shade - in app -> lock device - on home -> open shade - on home -> lock device - in overview -> open shade Test: manually sanity tested to make sure animations for more bubbles still work Test: manual - Open test bubble app - Open keyboard and send a bubble - The bubble should animate using a HUN since the keyboard is open - Swipe back to hide the keyboard - Observe that the bubble bar no longer shows to stash into the handle Change-Id: I754a5a9c8e961af0cdd5ccadf83d3081d4414c7e --- .../taskbar/bubbles/BubbleBarViewController.java | 13 ++++++++++++- .../taskbar/bubbles/BubbleStashController.java | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index f614dc66ea..45a9fa16e3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -98,7 +98,6 @@ public class BubbleBarViewController { mBarView = barView; mSystemUiProxy = SystemUiProxy.INSTANCE.get(mActivity); mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */); - mBubbleBarAlpha.setUpdateVisibility(true); mIconSize = activity.getResources().getDimensionPixelSize( R.dimen.bubblebar_icon_size); } @@ -408,7 +407,19 @@ public class BubbleBarViewController { b.getView().setOnClickListener(mBubbleClickListener); mBubbleDragController.setupBubbleView(b.getView()); + if (b instanceof BubbleBarOverflow) { + return; + } + if (suppressAnimation || !(b instanceof BubbleBarBubble bubble)) { + // the bubble bar and handle are initialized as part of the first bubble animation. + // if the animation is suppressed, immediately stash or show the bubble bar to + // ensure they've been initialized. + if (mTaskbarStashController.isInApp()) { + mBubbleStashController.stashBubbleBarImmediate(); + } else { + mBubbleStashController.showBubbleBarImmediate(); + } return; } animateBubbleNotification(bubble, isExpanding); diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java index 5d01b9bd08..74ddf90afc 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java @@ -418,6 +418,7 @@ public class BubbleStashController { /** Stashes the bubble bar immediately without animation. */ public void stashBubbleBarImmediate() { mHandleViewController.setTranslationYForSwipe(0); + mBubbleStashedHandleAlpha.setValue(1); mIconAlphaForStash.setValue(0); mIconTranslationYForStash.updateValue(getStashTranslation()); mIconScaleForStash.updateValue(STASHED_BAR_SCALE); From 93ee47f729055dc8d012e0538eb3de9cd7c44d01 Mon Sep 17 00:00:00 2001 From: Shamali P Date: Tue, 28 May 2024 13:13:44 +0000 Subject: [PATCH 034/143] Measure recommendation children using the provided available height We always want to measure the pages based on the provided height. Bug: 335715046 Test: Manual Flag: NONE BUGFIX Change-Id: I9de2ed1e0d4cc37d24435b9077e60bf5f0456091 --- .../widget/picker/WidgetRecommendationsView.java | 16 +++++++++++++--- .../widget/picker/WidgetsTwoPaneSheet.java | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java index 4f73e660d0..9260af9b22 100644 --- a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java +++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java @@ -53,6 +53,7 @@ import java.util.stream.Collectors; */ public final class WidgetRecommendationsView extends PagedView { private @Px float mAvailableHeight = Float.MAX_VALUE; + private @Px float mAvailableWidth = 0; private static final String INITIALLY_DISPLAYED_WIDGETS_STATE_KEY = "widgetRecommendationsView:mDisplayedWidgets"; private static final int MAX_CATEGORIES = 3; @@ -152,6 +153,7 @@ public final class WidgetRecommendationsView extends PagedView displayedWidgets = maybeDisplayInTable(recommendedWidgets, @@ -187,6 +189,7 @@ public final class WidgetRecommendationsView extends PagedView 0; if (hasMultiplePages) { - int finalWidth = MeasureSpec.getSize(widthMeasureSpec); int desiredHeight = 0; + int desiredWidth = Math.round(mAvailableWidth); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); - measureChild(child, widthMeasureSpec, heightMeasureSpec); + // Measure children based on available height and width. + measureChild(child, + MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(Math.round(mAvailableHeight), + MeasureSpec.AT_MOST)); // Use height of tallest child as we have limited height. - desiredHeight = Math.max(desiredHeight, child.getMeasuredHeight()); + int childHeight = child.getMeasuredHeight(); + desiredHeight = Math.max(desiredHeight, childHeight); } int finalHeight = resolveSizeAndState(desiredHeight, heightMeasureSpec, 0); + int finalWidth = resolveSizeAndState(desiredWidth, widthMeasureSpec, 0); + setMeasuredDimension(finalWidth, finalHeight); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java index f835e1860e..5d71db6e39 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java @@ -67,7 +67,7 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet { // This ratio defines the max percentage of content area that the recommendations can display // with respect to the bottom sheet's height. - private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.60f; + private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.70f; private FrameLayout mSuggestedWidgetsContainer; private WidgetsListHeader mSuggestedWidgetsHeader; private PackageUserKey mSuggestedWidgetsPackageUserKey; From 01d1c31ec714924b3d2e47d73b2a09ad88db348b Mon Sep 17 00:00:00 2001 From: Shamali P Date: Tue, 28 May 2024 13:13:58 +0000 Subject: [PATCH 035/143] Move item animator to its own class and use it only for full sheet Bug: 335715046 Test: Manual Flag: NONE BUGFIX Change-Id: I6977e9854edcee385f5b7075f62dd1d8ff8dfdce --- .../widget/picker/WidgetsFullSheet.java | 33 +--------- .../picker/WidgetsListItemAnimator.java | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 31 deletions(-) create mode 100644 src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java index 6aaa7d21af..3be6faa358 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java @@ -20,7 +20,6 @@ import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker; import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED; import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL; -import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_LIST; import android.animation.Animator; import android.content.Context; @@ -1023,35 +1022,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet default: break; } - mWidgetsListItemAnimator = new DefaultItemAnimator() { - @Override - public boolean animateChange(RecyclerView.ViewHolder oldHolder, - RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, - int toTop) { - // As we expand an item, the content / widgets list that appears (with add - // event) also gets change events as its previews load asynchronously. The - // super implementation of animateChange cancels the animations on it - breaking - // the "add animation". Instead, here, we skip "change" animation for content - // list - because we want it to either appear or disappear. And, the previews - // themselves have their own animation when loaded, so, we don't need change - // animations for them anyway. Below, we do-nothing. - if (oldHolder.getItemViewType() == VIEW_TYPE_WIDGETS_LIST) { - dispatchChangeStarting(oldHolder, true); - dispatchChangeFinished(oldHolder, true); - return true; - } - return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, - toTop); - } - }; - // Disable change animations because it disrupts the item focus upon adapter item - // change. - mWidgetsListItemAnimator.setSupportsChangeAnimations(false); - // Make the moves a bit faster, so that the amount of time for which user sees the - // bottom-sheet background before "add" animation starts is less making it smoother. - mWidgetsListItemAnimator.setChangeDuration(90); - mWidgetsListItemAnimator.setMoveDuration(90); - mWidgetsListItemAnimator.setAddDuration(300); + mWidgetsListItemAnimator = new WidgetsListItemAnimator(); } private int getEmptySpaceHeight() { @@ -1065,7 +1036,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet mWidgetsRecyclerView.setClipChildren(false); mWidgetsRecyclerView.setAdapter(mWidgetsListAdapter); mWidgetsRecyclerView.bindFastScrollbar(mFastScroller); - mWidgetsRecyclerView.setItemAnimator(mWidgetsListItemAnimator); + mWidgetsRecyclerView.setItemAnimator(isTwoPane() ? null : mWidgetsListItemAnimator); mWidgetsRecyclerView.setHeaderViewDimensionsProvider(WidgetsFullSheet.this); if (!isTwoPane()) { mWidgetsRecyclerView.setEdgeEffectFactory( diff --git a/src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java b/src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java new file mode 100644 index 0000000000..854700fed3 --- /dev/null +++ b/src/com/android/launcher3/widget/picker/WidgetsListItemAnimator.java @@ -0,0 +1,60 @@ +/* + * 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.widget.picker; + +import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_LIST; + +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; + +public class WidgetsListItemAnimator extends DefaultItemAnimator { + public static final int CHANGE_DURATION_MS = 90; + public static final int MOVE_DURATION_MS = 90; + public static final int ADD_DURATION_MS = 120; + + public WidgetsListItemAnimator() { + super(); + + // Disable change animations because it disrupts the item focus upon adapter item + // change. + setSupportsChangeAnimations(false); + // Make the moves a bit faster, so that the amount of time for which user sees the + // bottom-sheet background before "add" animation starts is less making it smoother. + setChangeDuration(CHANGE_DURATION_MS); + setMoveDuration(MOVE_DURATION_MS); + setAddDuration(ADD_DURATION_MS); + } + @Override + public boolean animateChange(RecyclerView.ViewHolder oldHolder, + RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, + int toTop) { + // As we expand an item, the content / widgets list that appears (with add + // event) also gets change events as its previews load asynchronously. The + // super implementation of animateChange cancels the animations on it - breaking + // the "add animation". Instead, here, we skip "change" animation for content + // list - because we want it to either appear or disappear. And, the previews + // themselves have their own animation when loaded, so, we don't need change + // animations for them anyway. Below, we do-nothing. + if (oldHolder.getItemViewType() == VIEW_TYPE_WIDGETS_LIST) { + dispatchChangeStarting(oldHolder, true); + dispatchChangeFinished(oldHolder, true); + return true; + } + return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, + toTop); + } +} From 7a183e40516abf58288b26ba79325695a4ee5ded Mon Sep 17 00:00:00 2001 From: Shamali P Date: Tue, 28 May 2024 13:14:15 +0000 Subject: [PATCH 036/143] Adjust previews in a row to align with each other and remove whitespace. - Introduces a WidgetTableRow that identifies preview height for all of its children while keeping them aligned with minimum whitespace - The fullSheet's move / change animations can conflict with the resize so, we wait for them before performing resize of the row. Bug: 335715046 Test: Manual Flag: NONE BUGFIX Change-Id: Id843430c7adfc228c219ba54d504baddba792df0 --- .../launcher3/dragndrop/AddItemActivity.java | 11 ++- .../android/launcher3/widget/WidgetCell.java | 86 ++++++++++++++++-- .../launcher3/widget/WidgetTableRow.java | 90 +++++++++++++++++++ .../launcher3/widget/WidgetsBottomSheet.java | 7 +- .../WidgetsListTableViewHolderBinder.java | 29 +++--- .../WidgetsRecommendationTableLayout.java | 9 +- 6 files changed, 208 insertions(+), 24 deletions(-) create mode 100644 src/com/android/launcher3/widget/WidgetTableRow.java diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java index ec0a222a8a..85eb39bab8 100644 --- a/src/com/android/launcher3/dragndrop/AddItemActivity.java +++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java @@ -91,7 +91,8 @@ import java.util.function.Supplier; */ @TargetApi(Build.VERSION_CODES.O) public class AddItemActivity extends BaseActivity - implements OnLongClickListener, OnTouchListener, AbstractSlideInView.OnCloseListener { + implements OnLongClickListener, OnTouchListener, AbstractSlideInView.OnCloseListener, + WidgetCell.PreviewReadyListener { private static final int SHADOW_SIZE = 10; @@ -142,6 +143,7 @@ public class AddItemActivity extends BaseActivity mDragLayer = findViewById(R.id.add_item_drag_layer); mDragLayer.recreateControllers(); mWidgetCell = findViewById(R.id.widget_cell); + mWidgetCell.addPreviewReadyListener(this); mAccessibilityManager = getApplicationContext().getSystemService(AccessibilityManager.class); @@ -454,4 +456,11 @@ public class AddItemActivity extends BaseActivity .withItemInfo((ItemInfo) mWidgetCell.getWidgetView().getTag()) .log(command); } + + @Override + public void onPreviewAvailable() { + // Set the preview height based on "the only" widget's preview. + mWidgetCell.setParentAlignedPreviewHeight(mWidgetCell.getPreviewContentHeight()); + mWidgetCell.post(mWidgetCell::requestLayout); + } } diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index eac2ce716a..2bb485aafa 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -103,6 +103,8 @@ public class WidgetCell extends LinearLayout { private Size mWidgetSize; private final DatabaseWidgetPreviewLoader mWidgetPreviewLoader; + @Nullable + private PreviewReadyListener mPreviewReadyListener = null; protected CancellableTask mActiveRequest; private boolean mAnimatePreview = true; @@ -118,7 +120,8 @@ public class WidgetCell extends LinearLayout { private CancellableTask mIconLoadRequest; private boolean mIsShowingAddButton = false; - + // Height enforced by the parent to align all widget cells displayed by it. + private int mParentAlignedPreviewHeight; public WidgetCell(Context context) { this(context, null); } @@ -190,6 +193,8 @@ public class WidgetCell extends LinearLayout { mWidgetDims.setText(null); mWidgetDescription.setText(null); mWidgetDescription.setVisibility(GONE); + mPreviewReadyListener = null; + mParentAlignedPreviewHeight = 0; showDescription(true); showDimensions(true); @@ -338,8 +343,8 @@ public class WidgetCell extends LinearLayout { private void updateAppWidgetHostScale(NavigableAppWidgetHostView view) { // Scale the content such that all of the content is visible - int contentWidth = view.getWidth(); - int contentHeight = view.getHeight(); + float contentWidth = view.getWidth(); + float contentHeight = view.getHeight(); if (view.getChildCount() == 1) { View content = view.getChildAt(0); @@ -359,6 +364,12 @@ public class WidgetCell extends LinearLayout { mAppWidgetHostViewScale = Math.min(pWidth / contentWidth, pHeight / contentHeight); } view.setScaleToFit(mAppWidgetHostViewScale); + + // layout based previews maybe ready at this point to inspect their inner height. + if (mPreviewReadyListener != null) { + mPreviewReadyListener.onPreviewAvailable(); + mPreviewReadyListener = null; + } } public WidgetImageView getWidgetView() { @@ -384,6 +395,12 @@ public class WidgetCell extends LinearLayout { removeView(mAppWidgetHostViewPreview); mAppWidgetHostViewPreview = null; } + + // Drawables of the image previews are available at this point to measure. + if (mPreviewReadyListener != null) { + mPreviewReadyListener.onPreviewAvailable(); + mPreviewReadyListener = null; + } } if (mAnimatePreview) { @@ -489,14 +506,20 @@ public class WidgetCell extends LinearLayout { // mPreviewContainerScale ensures the needed scaling with respect to original widget size. mAppWidgetHostViewScale = mPreviewContainerScale; containerLp.width = mPreviewContainerSize.getWidth(); - containerLp.height = mPreviewContainerSize.getHeight(); + int height = mPreviewContainerSize.getHeight(); // If we don't have enough available width, scale the preview container to fit. if (containerLp.width > maxWidth) { containerLp.width = maxWidth; mAppWidgetHostViewScale = (float) containerLp.width / mPreviewContainerSize.getWidth(); - containerLp.height = Math.round( - mPreviewContainerSize.getHeight() * mAppWidgetHostViewScale); + height = Math.round(mPreviewContainerSize.getHeight() * mAppWidgetHostViewScale); + } + + // Use parent aligned height in set. + if (mParentAlignedPreviewHeight > 0) { + containerLp.height = Math.min(height, mParentAlignedPreviewHeight); + } else { + containerLp.height = height; } // No need to call mWidgetImageContainer.setLayoutParams as we are in measure pass @@ -512,6 +535,42 @@ public class WidgetCell extends LinearLayout { } } + /** + * Sets the height of the preview as adjusted by the parent to have this cell's content aligned + * with other cells displayed by the parent. + */ + public void setParentAlignedPreviewHeight(int previewHeight) { + mParentAlignedPreviewHeight = previewHeight; + } + + /** + * Returns the height of the preview without any empty space. + * In case of appwidget host views, it returns the height of first child. This way, if preview + * view provided by an app doesn't fill bounds, this will return actual height without white + * space. + */ + public int getPreviewContentHeight() { + // By default assume scaled height. + int height = Math.round(mPreviewContainerScale * mWidgetSize.getHeight()); + + if (mWidgetImage != null && mWidgetImage.getDrawable() != null) { + // getBitmapBounds returns the scaled bounds. + Rect bitmapBounds = mWidgetImage.getBitmapBounds(); + height = bitmapBounds.height(); + } else if (mAppWidgetHostViewPreview != null + && mAppWidgetHostViewPreview.getChildCount() == 1) { + int contentHeight = Math.round( + mPreviewContainerScale * mWidgetSize.getHeight()); + int previewInnerHeight = Math.round( + mAppWidgetHostViewScale * mAppWidgetHostViewPreview.getChildAt( + 0).getMeasuredHeight()); + // Use either of the inner scaled height or the scaled widget height + height = Math.min(contentHeight, previewInnerHeight); + } + + return height; + } + /** * Loads a high resolution package icon to show next to the widget title. */ @@ -651,4 +710,19 @@ public class WidgetCell extends LinearLayout { } return false; } + + /** + * Listener to notify when previews are available. + */ + public void addPreviewReadyListener(PreviewReadyListener previewReadyListener) { + mPreviewReadyListener = previewReadyListener; + } + + /** + * Listener interface for subscribers to listen to preview's availability. + */ + public interface PreviewReadyListener { + /** Handler on to invoke when previews are available. */ + void onPreviewAvailable(); + } } diff --git a/src/com/android/launcher3/widget/WidgetTableRow.java b/src/com/android/launcher3/widget/WidgetTableRow.java new file mode 100644 index 0000000000..a5312ce4b7 --- /dev/null +++ b/src/com/android/launcher3/widget/WidgetTableRow.java @@ -0,0 +1,90 @@ +/* + * 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.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.TableRow; + +/** + * A row of {@link WidgetCell}s that can be displayed in a table. + */ +public class WidgetTableRow extends TableRow implements WidgetCell.PreviewReadyListener { + private int mNumOfReadyCells; + private int mNumOfCells; + private int mResizeDelay; + + public WidgetTableRow(Context context) { + super(context); + } + public WidgetTableRow(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void onPreviewAvailable() { + mNumOfReadyCells++; + + // Once all previews are loaded, find max visible height and adjust the preview containers. + if (mNumOfReadyCells == mNumOfCells) { + resize(); + } + } + + private void resize() { + int previewHeight = 0; + // get the maximum height of each widget preview + for (int i = 0; i < getChildCount(); i++) { + WidgetCell widgetCell = (WidgetCell) getChildAt(i); + previewHeight = Math.max(widgetCell.getPreviewContentHeight(), previewHeight); + } + if (mResizeDelay > 0) { + postDelayed(() -> setAlpha(1f), mResizeDelay); + } + if (previewHeight > 0) { + for (int i = 0; i < getChildCount(); i++) { + WidgetCell widgetCell = (WidgetCell) getChildAt(i); + widgetCell.setParentAlignedPreviewHeight(previewHeight); + widgetCell.postDelayed(widgetCell::requestLayout, mResizeDelay); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + } + + /** + * Sets up the row to display the provided number of numOfCells. + * + * @param numOfCells number of numOfCells in the row + * @param resizeDelayMs time to wait in millis before making any layout size adjustments e.g. we + * want to wait for list expand collapse animation before resizing the + * cell previews. + */ + public void setupRow(int numOfCells, int resizeDelayMs) { + mNumOfCells = numOfCells; + mNumOfReadyCells = 0; + + mResizeDelay = resizeDelayMs; + // For delayed resize, reveal contents only after resize is done. + if (mResizeDelay > 0) { + setAlpha(0); + } + } +} diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java index 4ea24265c3..894099de74 100644 --- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java +++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java @@ -31,7 +31,6 @@ import android.view.ViewParent; import android.view.animation.Interpolator; import android.widget.ScrollView; import android.widget.TableLayout; -import android.widget.TableRow; import android.widget.TextView; import androidx.annotation.Px; @@ -137,8 +136,9 @@ public class WidgetsBottomSheet extends BaseWidgetSheet { mActivityContext.getDeviceProfile(), mMaxHorizontalSpan, mWidgetCellHorizontalPadding) .forEach(row -> { - TableRow tableRow = new TableRow(getContext()); + WidgetTableRow tableRow = new WidgetTableRow(getContext()); tableRow.setGravity(Gravity.TOP); + tableRow.setupRow(row.size(), /*resizeDelayMs=*/ 0); row.forEach(widgetItem -> { WidgetCell widget = addItemCell(tableRow); widget.applyFromCellItem(widgetItem); @@ -163,9 +163,10 @@ public class WidgetsBottomSheet extends BaseWidgetSheet { return super.onControllerInterceptTouchEvent(ev); } - protected WidgetCell addItemCell(ViewGroup parent) { + protected WidgetCell addItemCell(WidgetTableRow parent) { WidgetCell widget = (WidgetCell) LayoutInflater.from(getContext()) .inflate(R.layout.widget_cell, parent, false); + widget.addPreviewReadyListener(parent); widget.setOnClickListener(this); View previewContainer = widget.findViewById(R.id.widget_preview_container); diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java index 56352ccc9f..45d733a3a5 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java +++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java @@ -15,6 +15,11 @@ */ package com.android.launcher3.widget.picker; +import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.CHANGE_DURATION_MS; +import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.MOVE_DURATION_MS; + +import static android.animation.ValueAnimator.areAnimatorsEnabled; + import android.content.Context; import android.graphics.Bitmap; import android.util.Log; @@ -26,7 +31,6 @@ import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.TableLayout; -import android.widget.TableRow; import androidx.annotation.NonNull; import androidx.annotation.Px; @@ -36,6 +40,7 @@ import com.android.launcher3.model.WidgetItem; import com.android.launcher3.recyclerview.ViewHolderBinder; import com.android.launcher3.views.ActivityContext; import com.android.launcher3.widget.WidgetCell; +import com.android.launcher3.widget.WidgetTableRow; import com.android.launcher3.widget.model.WidgetsListContentEntry; import com.android.launcher3.widget.util.WidgetsTableUtils; @@ -111,17 +116,15 @@ public final class WidgetsListTableViewHolderBinder for (int i = 0; i < widgetItemsTable.size(); i++) { List widgetItemsPerRow = widgetItemsTable.get(i); for (int j = 0; j < widgetItemsPerRow.size(); j++) { - TableRow row = (TableRow) table.getChildAt(i); + WidgetTableRow row = (WidgetTableRow) table.getChildAt(i); row.setVisibility(View.VISIBLE); WidgetCell widget = (WidgetCell) row.getChildAt(j); widget.clear(); + widget.addPreviewReadyListener(row); WidgetItem widgetItem = widgetItemsPerRow.get(j); widget.setVisibility(View.VISIBLE); - // When preview loads, notify adapter to rebind the item and possibly animate - widget.applyFromCellItem(widgetItem, - bitmap -> holder.onPreviewLoaded(Pair.create(widgetItem, bitmap)), - holder.previewCache.get(widgetItem)); + widget.applyFromCellItem(widgetItem); widget.requestLayout(); } } @@ -143,14 +146,19 @@ public final class WidgetsListTableViewHolderBinder for (int i = 0; i < widgetItemsTable.size(); i++) { List widgetItems = widgetItemsTable.get(i); - TableRow tableRow; + WidgetTableRow tableRow; if (i < table.getChildCount()) { - tableRow = (TableRow) table.getChildAt(i); + tableRow = (WidgetTableRow) table.getChildAt(i); } else { - tableRow = new TableRow(table.getContext()); + tableRow = new WidgetTableRow(table.getContext()); tableRow.setGravity(Gravity.TOP); table.addView(tableRow); } + // Pass resize delay to let the "move" and "change" animations run before resizing the + // row. + tableRow.setupRow(widgetItems.size(), + /*resizeDelayMs=*/ + areAnimatorsEnabled() ? (CHANGE_DURATION_MS + MOVE_DURATION_MS) : 0); if (tableRow.getChildCount() > widgetItems.size()) { for (int j = widgetItems.size(); j < tableRow.getChildCount(); j++) { tableRow.getChildAt(j).setVisibility(View.GONE); @@ -161,6 +169,7 @@ public final class WidgetsListTableViewHolderBinder R.layout.widget_cell, tableRow, false); // set up touch. widget.setOnClickListener(mIconClickListener); + widget.addPreviewReadyListener(tableRow); View preview = widget.findViewById(R.id.widget_preview_container); preview.setOnClickListener(mIconClickListener); preview.setOnLongClickListener(mIconLongClickListener); @@ -176,7 +185,7 @@ public final class WidgetsListTableViewHolderBinder int numOfRows = holder.tableContainer.getChildCount(); holder.previewCache.clear(); for (int i = 0; i < numOfRows; i++) { - TableRow tableRow = (TableRow) holder.tableContainer.getChildAt(i); + WidgetTableRow tableRow = (WidgetTableRow) holder.tableContainer.getChildAt(i); int numOfCols = tableRow.getChildCount(); for (int j = 0; j < numOfCols; j++) { WidgetCell widget = (WidgetCell) tableRow.getChildAt(j); diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java index 6dbad5c7d2..1ed3d884c4 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java +++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java @@ -27,9 +27,7 @@ import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.TableLayout; -import android.widget.TableRow; import androidx.annotation.Nullable; import androidx.annotation.Px; @@ -38,6 +36,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.widget.WidgetCell; +import com.android.launcher3.widget.WidgetTableRow; import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize; import java.util.ArrayList; @@ -105,7 +104,8 @@ public final class WidgetsRecommendationTableLayout extends TableLayout { for (int i = 0; i < recommendationTable.size(); i++) { List widgetItems = recommendationTable.get(i); - TableRow tableRow = new TableRow(getContext()); + WidgetTableRow tableRow = new WidgetTableRow(getContext()); + tableRow.setupRow(widgetItems.size(), /*resizeDelayMs=*/ 0); tableRow.setGravity(Gravity.TOP); for (WidgetItem widgetItem : widgetItems) { WidgetCell widgetCell = addItemCell(tableRow); @@ -121,9 +121,10 @@ public final class WidgetsRecommendationTableLayout extends TableLayout { setVisibility(VISIBLE); } - private WidgetCell addItemCell(ViewGroup parent) { + private WidgetCell addItemCell(WidgetTableRow parent) { WidgetCell widget = (WidgetCell) LayoutInflater.from( getContext()).inflate(R.layout.widget_cell, parent, false); + widget.addPreviewReadyListener(parent); widget.setOnClickListener(mWidgetCellOnClickListener); View previewContainer = widget.findViewById(R.id.widget_preview_container); From ee5867e98054b9564b8a8a19981b38bd9074b998 Mon Sep 17 00:00:00 2001 From: Liam Lee Pong Lam Date: Mon, 3 Jun 2024 19:00:14 +0000 Subject: [PATCH 037/143] Revert "[Launcher3] Hide keyboard when fastscroller scrolling down and keyboard" This reverts commit 883a79db715258e92b738357771078548920df65. Reason for revert: Revert this change because it caused other bug b/343285163 Change-Id: I1fdb21cc4a5cdcf2c22e9b1927753b290626289c --- .../views/RecyclerViewFastScroller.java | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java index cdbd0c0be7..df8f635525 100644 --- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java +++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java @@ -109,13 +109,6 @@ public class RecyclerViewFastScroller extends View { private float mLastTouchY; private boolean mIsDragging; - /** - * Tracks whether a keyboard hide request has been sent due to downward scrolling. - *

- * Set to true when scrolling down and reset when scrolling up to prevents redundant hide - * requests during continuous downward scrolls. - */ - private boolean mRequestedHideKeyboard; private boolean mIsThumbDetached; private final boolean mCanThumbDetach; private boolean mIgnoreDragGesture; @@ -248,7 +241,6 @@ public class RecyclerViewFastScroller extends View { public boolean handleTouchEvent(MotionEvent ev, Point offset) { int x = (int) ev.getX() - offset.x; int y = (int) ev.getY() - offset.y; - ActivityContext activityContext = ActivityContext.lookupContext(getContext()); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: @@ -256,7 +248,6 @@ public class RecyclerViewFastScroller extends View { mDownX = x; mDownY = mLastY = y; mDownTimeStampMillis = ev.getDownTime(); - mRequestedHideKeyboard = false; if ((Math.abs(mDy) < mDeltaThreshold && mRv.getScrollState() != SCROLL_STATE_IDLE)) { @@ -269,15 +260,6 @@ public class RecyclerViewFastScroller extends View { } break; case MotionEvent.ACTION_MOVE: - if (y > mLastY) { - if (!mRequestedHideKeyboard) { - activityContext.hideKeyboard(); - } - mRequestedHideKeyboard = true; - } else { - mRequestedHideKeyboard = false; - } - mLastY = y; int absDeltaY = Math.abs(y - mDownY); int absDeltaX = Math.abs(x - mDownX); @@ -312,6 +294,7 @@ public class RecyclerViewFastScroller extends View { } private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) { + ActivityContext.lookupContext(getContext()).hideKeyboard(); mIsDragging = true; if (mCanThumbDetach) { mIsThumbDetached = true; From ee3822491009e5c289e21ae345f466e809639959 Mon Sep 17 00:00:00 2001 From: Anton Vayvod Date: Tue, 28 May 2024 21:26:25 -0400 Subject: [PATCH 038/143] Guard Flags references with a check for running on Android V. Otherwise, Launcher3 next build crashes on non-V devices. Bug: NONE Trivial cleanup. Test: manual Flag: NONE The change deals with flags Change-Id: I9d9335ea1cb0f299aa5af8095ff1ea2f98c23542 --- src/com/android/launcher3/Launcher.java | 8 +++++--- src/com/android/launcher3/LauncherAppState.java | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7f72526942..6d2c8fab42 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -163,6 +163,7 @@ import androidx.annotation.RequiresApi; import androidx.annotation.StringRes; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; +import androidx.core.os.BuildCompat; import androidx.window.embedding.RuleController; import com.android.launcher3.DropTarget.DragObject; @@ -589,7 +590,8 @@ public class Launcher extends StatefulActivity setTitle(R.string.home_screen); mStartupLatencyLogger.logEnd(LAUNCHER_LATENCY_STARTUP_ACTIVITY_ON_CREATE); - if (com.android.launcher3.Flags.enableTwoPaneLauncherSettings()) { + if (BuildCompat.isAtLeastV() + && com.android.launcher3.Flags.enableTwoPaneLauncherSettings()) { RuleController.getInstance(this).setRules( RuleController.parseRules(this, R.xml.split_configuration)); } @@ -2789,7 +2791,7 @@ public class Launcher extends StatefulActivity } private void updateDisallowBack() { - if (Flags.enableDesktopWindowingMode()) { + if (BuildCompat.isAtLeastV() && Flags.enableDesktopWindowingMode()) { // TODO(b/330183377) disable back in launcher when when we productionize return; } @@ -3146,4 +3148,4 @@ public class Launcher extends StatefulActivity } // End of Getters and Setters -} \ No newline at end of file +} diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index a4ae1c8050..3b8ff62d8a 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -39,6 +39,7 @@ import android.os.UserHandle; import android.util.Log; import androidx.annotation.Nullable; +import androidx.core.os.BuildCompat; import com.android.launcher3.graphics.IconShape; import com.android.launcher3.icons.IconCache; @@ -107,7 +108,7 @@ public class LauncherAppState implements SafeCloseable { mOnTerminateCallback.add(() -> mContext.getSystemService(LauncherApps.class).unregisterCallback(callbacks)); - if (Flags.enableSupportForArchiving()) { + if (BuildCompat.isAtLeastV() && Flags.enableSupportForArchiving()) { ArchiveCompatibilityParams params = new ArchiveCompatibilityParams(); params.setEnableUnarchivalConfirmation(false); launcherApps.setArchiveCompatibility(params); From 018074351c1579653b7454a4f1c332aae19cb674 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Mon, 3 Jun 2024 12:58:34 -0700 Subject: [PATCH 039/143] Animate -1 to recents Fix: 343770316 Test: manual - record a video Flag: com.android.launcher3.use_activity_overlay Change-Id: I74346f060ea93dbc8fc0a1c3290d4996d89ec062 --- .../src/com/android/quickstep/LauncherActivityInterface.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java index 811b9fd4cd..08c2e1ca29 100644 --- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java @@ -308,7 +308,8 @@ public final class LauncherActivityInterface extends return; } LauncherOverlayManager om = launcher.getOverlayManager(); - if (!launcher.isStarted() || launcher.isForceInvisible()) { + if (!SystemUiProxy.INSTANCE.get(launcher).getHomeVisibilityState().isHomeVisible() + || launcher.isForceInvisible()) { om.hideOverlay(false /* animate */); } else { om.hideOverlay(150); From be10c0b10c1136c79638d47fb35266eeb0e4f72a Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 21 May 2024 17:26:17 +0000 Subject: [PATCH 040/143] Add flag for Recents in Taskbar Flag: com.android.launcher3.enable_recents_in_taskbar Test: none Bug: 315354060 Change-Id: I5b757558ab8e5905b4142146901b68f55d0c7ef8 --- aconfig/launcher.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig index 9147e4c54f..22fe82b0ec 100644 --- a/aconfig/launcher.aconfig +++ b/aconfig/launcher.aconfig @@ -284,3 +284,10 @@ flag { description: "Enables folders in all apps" bug: "341582436" } + +flag { + name: "enable_recents_in_taskbar" + namespace: "launcher" + description: "Replace hybrid hotseat app predictions with strictly Recent Apps" + bug: "315354060" +} From e48009919dde13fded7242549413b018daa64a04 Mon Sep 17 00:00:00 2001 From: "Liam, Lee Pong Lam" Date: Tue, 4 Jun 2024 00:34:49 +0000 Subject: [PATCH 041/143] [Launcher3] Hide keyboard when fastscroller scrolling down and keyboard shown Implement keyboard hiding logic: Hide keyboard when scrolling down (y > mLastY) unless already requested (mRequestedHideKeyboard). Track hide request state to prevent redundant calls. New added logic: Only hide keyobard while dragging the scrollbar result video: https://photos.app.goo.gl/e4dYUUiUN3BujNUz9 Bug: 333967597 Flag: EXEMPT bugfix Test: Manual Change-Id: Id672763c69cbb37aeb7a1fd3f17eb168de9f49b4 --- .../views/RecyclerViewFastScroller.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java index df8f635525..fa17b7bcfe 100644 --- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java +++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java @@ -109,6 +109,13 @@ public class RecyclerViewFastScroller extends View { private float mLastTouchY; private boolean mIsDragging; + /** + * Tracks whether a keyboard hide request has been sent due to downward scrolling. + *

+ * Set to true when scrolling down and reset when scrolling up to prevents redundant hide + * requests during continuous downward scrolls. + */ + private boolean mRequestedHideKeyboard; private boolean mIsThumbDetached; private final boolean mCanThumbDetach; private boolean mIgnoreDragGesture; @@ -127,6 +134,7 @@ public class RecyclerViewFastScroller extends View { protected FastScrollRecyclerView mRv; private RecyclerView.OnScrollListener mOnScrollListener; + private final ActivityContext mActivityContext; private int mDownX; private int mDownY; @@ -163,7 +171,7 @@ public class RecyclerViewFastScroller extends View { mDeltaThreshold = res.getDisplayMetrics().density * SCROLL_DELTA_THRESHOLD_DP; mScrollbarLeftOffsetTouchDelegate = res.getDisplayMetrics().density * SCROLLBAR_LEFT_OFFSET_TOUCH_DELEGATE_DP; - + mActivityContext = ActivityContext.lookupContext(context); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RecyclerViewFastScroller, defStyleAttr, 0); mCanThumbDetach = ta.getBoolean(R.styleable.RecyclerViewFastScroller_canThumbDetach, false); @@ -248,6 +256,7 @@ public class RecyclerViewFastScroller extends View { mDownX = x; mDownY = mLastY = y; mDownTimeStampMillis = ev.getDownTime(); + mRequestedHideKeyboard = false; if ((Math.abs(mDy) < mDeltaThreshold && mRv.getScrollState() != SCROLL_STATE_IDLE)) { @@ -260,6 +269,7 @@ public class RecyclerViewFastScroller extends View { } break; case MotionEvent.ACTION_MOVE: + boolean isScrollingDown = y > mLastY; mLastY = y; int absDeltaY = Math.abs(y - mDownY); int absDeltaX = Math.abs(x - mDownX); @@ -275,6 +285,14 @@ public class RecyclerViewFastScroller extends View { } } if (mIsDragging) { + if (isScrollingDown) { + if (!mRequestedHideKeyboard) { + mActivityContext.hideKeyboard(); + } + mRequestedHideKeyboard = true; + } else { + mRequestedHideKeyboard = false; + } updateFastScrollSectionNameAndThumbOffset(y); } break; @@ -294,7 +312,6 @@ public class RecyclerViewFastScroller extends View { } private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) { - ActivityContext.lookupContext(getContext()).hideKeyboard(); mIsDragging = true; if (mCanThumbDetach) { mIsThumbDetached = true; From 4ff619a6109850c888feeb435ca837d7eba12fca Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 3 Jun 2024 18:20:15 -0700 Subject: [PATCH 042/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I4e0f4e61a5e6957bd6d52ede541d1dfe0523ab74 --- res/values-af/strings.xml | 2 ++ res/values-am/strings.xml | 2 ++ res/values-ar/strings.xml | 2 ++ res/values-as/strings.xml | 2 ++ res/values-az/strings.xml | 2 ++ res/values-b+sr+Latn/strings.xml | 1 + res/values-be/strings.xml | 2 ++ res/values-bg/strings.xml | 2 ++ res/values-bn/strings.xml | 2 ++ res/values-bs/strings.xml | 2 ++ res/values-ca/strings.xml | 2 ++ res/values-cs/strings.xml | 2 ++ res/values-da/strings.xml | 2 ++ res/values-de/strings.xml | 2 ++ res/values-el/strings.xml | 2 ++ res/values-en-rAU/strings.xml | 2 ++ res/values-en-rCA/strings.xml | 1 + res/values-en-rGB/strings.xml | 2 ++ res/values-en-rIN/strings.xml | 2 ++ res/values-en-rXC/strings.xml | 1 + res/values-es-rUS/strings.xml | 2 ++ res/values-es/strings.xml | 2 ++ res/values-et/strings.xml | 1 + res/values-eu/strings.xml | 2 ++ res/values-fa/strings.xml | 2 ++ res/values-fi/strings.xml | 2 ++ res/values-fr-rCA/strings.xml | 2 ++ res/values-fr/strings.xml | 2 ++ res/values-gl/strings.xml | 2 ++ res/values-gu/strings.xml | 2 ++ res/values-hi/strings.xml | 2 ++ res/values-hr/strings.xml | 2 ++ res/values-hu/strings.xml | 2 ++ res/values-hy/strings.xml | 2 ++ res/values-in/strings.xml | 2 ++ res/values-is/strings.xml | 2 ++ res/values-it/strings.xml | 2 ++ res/values-iw/strings.xml | 2 ++ res/values-ja/strings.xml | 1 + res/values-ka/strings.xml | 1 + res/values-kk/strings.xml | 2 ++ res/values-km/strings.xml | 2 ++ res/values-kn/strings.xml | 2 ++ res/values-ko/strings.xml | 2 ++ res/values-ky/strings.xml | 2 ++ res/values-lo/strings.xml | 2 ++ res/values-lt/strings.xml | 1 + res/values-lv/strings.xml | 2 ++ res/values-mk/strings.xml | 2 ++ res/values-ml/strings.xml | 2 ++ res/values-mn/strings.xml | 2 ++ res/values-mr/strings.xml | 1 + res/values-ms/strings.xml | 2 ++ res/values-my/strings.xml | 1 + res/values-nb/strings.xml | 2 ++ res/values-ne/strings.xml | 2 ++ res/values-nl/strings.xml | 2 ++ res/values-or/strings.xml | 2 ++ res/values-pa/strings.xml | 4 +++- res/values-pl/strings.xml | 2 ++ res/values-pt-rPT/strings.xml | 1 + res/values-pt/strings.xml | 2 ++ res/values-ro/strings.xml | 2 ++ res/values-ru/strings.xml | 2 ++ res/values-si/strings.xml | 2 ++ res/values-sk/strings.xml | 2 ++ res/values-sl/strings.xml | 1 + res/values-sq/strings.xml | 2 ++ res/values-sr/strings.xml | 1 + res/values-sv/strings.xml | 2 ++ res/values-sw/strings.xml | 2 ++ res/values-ta/strings.xml | 5 +++-- res/values-te/strings.xml | 4 +++- res/values-th/strings.xml | 2 ++ res/values-tl/strings.xml | 2 ++ res/values-tr/strings.xml | 2 ++ res/values-uk/strings.xml | 2 ++ res/values-ur/strings.xml | 2 ++ res/values-uz/strings.xml | 2 ++ res/values-vi/strings.xml | 2 ++ res/values-zh-rCN/strings.xml | 2 ++ res/values-zh-rHK/strings.xml | 2 ++ res/values-zh-rTW/strings.xml | 2 ++ res/values-zu/strings.xml | 4 +++- 84 files changed, 160 insertions(+), 5 deletions(-) diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index 1d333fde88..e18d9cd18f 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -29,6 +29,8 @@ "Tuis" "Verdeelde skerm" "Programinligting vir %1$s" + + "Stoor apppaar" "%1$s | %2$s" "Hierdie apppaar word nie op hierdie toestel gesteun nie" diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index f57812e46c..39dbfef8dc 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -29,6 +29,8 @@ "መነሻ" "የተከፈለ ማያ ገፅ" "የመተግበሪያ መረጃ ለ%1$s" + + "የመተግበሪያ ጥምረትን ያስቀምጡ" "%1$s | %2$s" "ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index e6f8d4aa87..1143042949 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -29,6 +29,8 @@ "الشاشة الرئيسية" "تقسيم الشاشة" "‏معلومات تطبيق %1$s" + + "حفظ استخدام التطبيقين معًا" "%1$s | ‏%2$s" "لا يمكن استخدام هذين التطبيقَين في الوقت نفسه على هذا الجهاز" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index 54cc638dce..ed4bb975ae 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -29,6 +29,8 @@ "গৃহ স্ক্ৰীন" "বিভাজিত স্ক্ৰীন" "%1$sৰ বাবে এপৰ তথ্য" + + "এপৰ পেয়াৰ ছেভ কৰক" "%1$s | %2$s" "এই ডিভাইচটোত এই এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো সমৰ্থিত নহয়" diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 2f71bbdfa7..e8273423af 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -29,6 +29,8 @@ "Əsas səhifə" "Ekran bölünməsi" "%1$s ilə bağlı tətbiq məlumatı" + + "Tətbiq cütünü saxlayın" "%1$s | %2$s" "Bu tətbiq cütü bu cihazda dəstəklənmir" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 7858529ece..30ba09ce2b 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -29,6 +29,7 @@ "Početni ekran" "Podeljeni ekran" "Informacije o aplikaciji za: %1$s" + "Podešavanja potrošnje za %1$s" "Sačuvaj par aplikacija" "%1$s | %2$s" "Ovaj par aplikacija nije podržan na ovom uređaju" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index c3359c8172..3ece170259 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -29,6 +29,8 @@ "Галоўны экран" "Падзелены экран" "Інфармацыя пра праграму для: %1$s" + + "Захаваць спалучэнне праграм" "%1$s | %2$s" "Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 26044e75e8..4d23773c3c 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -29,6 +29,8 @@ "Начален екран" "Разделен екран" "Информация за приложението за %1$s" + + "Запазване на двойката приложения" "%1$s | %2$s" "Тази двойка приложения не се поддържа на устройството" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index a159bd9d76..83f4ba1ac8 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -29,6 +29,8 @@ "হোম" "স্প্লিট স্ক্রিন" "%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য" + + "অ্যাপ পেয়ার সেভ করুন" "%1$s | %2$s" "এই ডিভাইসে এই অ্যাপ পেয়ারটি কাজ করে না" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 8b2e821c76..2c5e22a601 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -29,6 +29,8 @@ "Početni ekran" "Podijeljeni ekran" "Informacije o aplikaciji %1$s" + + "Sačuvaj par aplikacija" "%1$s | %2$s" "Par aplikacija nije podržan na uređaju" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index c621b1cc55..f275e49ee9 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -29,6 +29,8 @@ "Inici" "Pantalla dividida" "Informació de l\'aplicació %1$s" + + "Desa la parella d\'aplicacions" "%1$s | %2$s" "Aquesta parella d\'aplicacions no s\'admet en aquest dispositiu" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 8b2e71672d..c499a9a00a 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -29,6 +29,8 @@ "Domů" "Rozdělit obrazovku" "Informace o aplikaci %1$s" + + "Uložit dvojici aplikací" "%1$s | %2$s" "Tento pár aplikací není na tomto zařízení podporován" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index b41344083d..f2c08fafbd 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -29,6 +29,8 @@ "Startskærm" "Opdel skærm" "Appinfo for %1$s" + + "Gem appsammenknytning" "%1$s | %2$s" "Denne appsammenknytning understøttes ikke på enheden" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 42e3bacadc..f5ecf59e19 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -29,6 +29,8 @@ "Startbildschirm" "Splitscreen" "App-Info für %1$s" + + "App-Paar speichern" "%1$s | %2$s" "Dieses App-Paar wird auf diesem Gerät nicht unterstützt" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 4eac9caf9d..1c4700a86e 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -29,6 +29,8 @@ "Αρχική οθόνη" "Διαχωρισμός οθόνης" "Πληροφορίες εφαρμογής για %1$s" + + "Αποθήκευση ζεύγους εφαρμογών" "%1$s | %2$s" "Αυτό το ζεύγος εφαρμογών δεν υποστηρίζεται σε αυτή τη συσκευή" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 7c78fc7d40..27bcb658ae 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -29,6 +29,8 @@ "Home" "Split screen" "App info for %1$s" + + "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index e6a7ea157a..f672a827d5 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -29,6 +29,7 @@ "Home" "Split screen" "App info for %1$s" + "Usage settings for %1$s" "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 7c78fc7d40..27bcb658ae 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -29,6 +29,8 @@ "Home" "Split screen" "App info for %1$s" + + "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 7c78fc7d40..27bcb658ae 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -29,6 +29,8 @@ "Home" "Split screen" "App info for %1$s" + + "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index 13616d6a57..706c65c525 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -29,6 +29,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎Home‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎Split screen‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎App info for %1$s‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎Usage settings for %1$s‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‎‏‏‎Save app pair‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ | ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‎‎This app pair isn\'t supported on this device‎‏‎‎‏‎" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 71a48cb324..3ba7ece050 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -29,6 +29,8 @@ "Pantalla principal" "Pantalla dividida" "Información de la app de %1$s" + + "Guardar vinculación" "%1$s | %2$s" "No se admite esta vinculación de apps en este dispositivo" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index b5208bd504..7309e58e6f 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -29,6 +29,8 @@ "Inicio" "Pantalla dividida" "Información de la aplicación %1$s" + + "Guardar apps emparejadas" "%1$s | %2$s" "El dispositivo no admite esta aplicación emparejada" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 20a99d3e51..13500b593b 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -29,6 +29,7 @@ "Avakuva" "Jagatud ekraanikuva" "Rakenduse teave: %1$s" + "Kasutuse seaded: %1$s" "Salvesta rakendusepaar" "%1$s | %2$s" "See rakendusepaar ei ole selles seadmes toetatud" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index a477580bde..d1ff4347aa 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -29,6 +29,8 @@ "Orri nagusia" "Pantaila zatitzea" "%1$s aplikazioari buruzko informazioa" + + "Gorde aplikazio parea" "%1$s | %2$s" "Aplikazio pare hori ez da onartzen gailu honetan" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index bdf4736cec..367945b13c 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -29,6 +29,8 @@ "صفحه اصلی" "صفحهٔ دونیمه" "‏اطلاعات برنامه %1$s" + + "ذخیره جفت برنامه" "%1$s | %2$s" "از این جفت برنامه در این دستگاه پشتیبانی نمی‌شود" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index e934044c0a..5f7df00ceb 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -29,6 +29,8 @@ "Etusivu" "Jaettu näyttö" "Sovellustiedot: %1$s" + + "Tallenna sovelluspari" "%1$s | %2$s" "Sovellusparia ei tueta tällä laitteella" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 4372caa75a..9775dbcc5a 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -29,6 +29,8 @@ "Accueil" "Écran divisé" "Renseignements sur l\'appli pour %1$s" + + "Enr. paire d\'applis" "%1$s | %2$s" "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 841fc84d77..53a30d317d 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -29,6 +29,8 @@ "Accueil" "Écran partagé" "Infos sur l\'appli pour %1$s" + + "Enregistrer la paire d\'applis" "%1$s | %2$s" "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 83fcbcd8d6..d651692509 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -29,6 +29,8 @@ "Inicio" "Pantalla dividida" "Información da aplicación para %1$s" + + "Gardar parella de apps" "%1$s | %2$s" "O dispositivo non admite este emparellamento de aplicacións" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 963c6d109b..89291bda88 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -29,6 +29,8 @@ "હોમ સ્ક્રીન" "સ્ક્રીનને વિભાજિત કરો" "%1$s માટે ઍપ માહિતી" + + "ઍપની જોડી સાચવો" "%1$s | %2$s" "આ ડિવાઇસ પર, આ ઍપની જોડીને સપોર્ટ આપવામાં આવતો નથી" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index f2ac2e8526..d70bf08edf 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -29,6 +29,8 @@ "होम स्क्रीन" "स्प्लिट स्क्रीन" "%1$s के लिए ऐप्लिकेशन की जानकारी" + + "ऐप पेयर सेव करें" "%1$s | %2$s" "साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन, इस डिवाइस पर काम नहीं कर सकते" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index fec8e2893f..19658f6dd1 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -29,6 +29,8 @@ "Početni zaslon" "Podijeljeni zaslon" "Informacije o aplikaciji %1$s" + + "Spremi par aplikacija" "%1$s | %2$s" "Taj par aplikacija nije podržan na ovom uređaju" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index f69e1fb872..96e4981246 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -29,6 +29,8 @@ "Kezdőképernyő" "Osztott képernyő" "Alkalmazásinformáció a következőhöz: %1$s" + + "Alkalmazáspár mentése" "%1$s | %2$s" "Ezt az alkalmazáspárt nem támogatja az eszköz" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 7e220bf2b2..e2b6d34235 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -29,6 +29,8 @@ "Հիմնական էկրան" "Տրոհել էկրանը" "Տեղեկություններ %1$s հավելվածի մասին" + + "Պահել հավելվ. զույգը" "%1$s | %2$s" "Հավելվածների զույգը չի աջակցվում այս սարքում" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index fc81717371..a86380e5da 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -29,6 +29,8 @@ "Layar utama" "Layar terpisah" "Info aplikasi untuk %1$s" + + "Simpan pasangan aplikasi" "%1$s | %2$s" "Pasangan aplikasi ini tidak didukung di perangkat ini" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 5339b9391e..d903d1ae20 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -29,6 +29,8 @@ "Heim" "Skipta skjá" "Upplýsingar um forrit fyrir %1$s" + + "Vista forritapar" "%1$s | %2$s" "Þetta forritapar er ekki stutt í þessu tæki" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 5ef0145e33..3895409034 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -29,6 +29,8 @@ "Home" "Schermo diviso" "Informazioni sull\'app %1$s" + + "Salva coppia di app" "%1$s | %2$s" "Questa coppia di app non è supportata su questo dispositivo" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 0d18cdf94f..aea1fa65b1 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -29,6 +29,8 @@ "בית" "מסך מפוצל" "‏פרטים על האפליקציה %1$s" + + "שמירת צמד אפליקציות" "%1$s | %2$s" "צמד האפליקציות הזה לא נתמך במכשיר הזה" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 163afd4318..c349e546b3 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -29,6 +29,7 @@ "ホーム" "分割画面" "%1$s のアプリ情報" + "%1$s の使用設定" "アプリのペア設定を保存" "%1$s | %2$s" "このデバイスは、このアプリのペア設定に対応していません" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index d7157e9ac9..fecd50e19b 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -29,6 +29,7 @@ "მთავარი გვერდი" "ეკრანის გაყოფა" "%1$s-ის აპის ინფო" + "გამოყენების პარამეტრები %1$s-ისთვის" "აპთა წყვილის შენახვა" "%1$s | %2$s" "ამ მოწყობილობაზე აღნიშნული აპთა წყვილი არ არის მხარდაჭერილი" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index c53cd033da..f3aa5f67e7 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -29,6 +29,8 @@ "Негізгі экран" "Экранды бөлу" "%1$s қолданбасы туралы ақпарат" + + "Қолданбаларды жұптау әрекетін сақтау" "%1$s | %2$s" "Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды." diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index f0c9fd9be8..1f73d4c25d 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -29,6 +29,8 @@ "អេក្រង់ដើម" "មុខងារ​បំបែកអេក្រង់" "ព័ត៌មានកម្មវិធី​សម្រាប់ %1$s" + + "រក្សាទុកគូកម្មវិធី" "%1$s | %2$s" "មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 9a81382e8e..309a1fb431 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -29,6 +29,8 @@ "ಹೋಮ್" "ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್" "%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ" + + "ಆ್ಯಪ್ ಪೇರ್ ಸೇವ್ ಮಾಡಿ" "%1$s | %2$s" "ಈ ಆ್ಯಪ್ ಜೋಡಿಯು ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 6ff9d90fb7..cfc04ef4a7 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -29,6 +29,8 @@ "홈" "화면 분할" "%1$s 앱 정보" + + "앱 페어링 저장" "%1$s | %2$s" "이 앱 페어링은 이 기기에서 지원되지 않습니다" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 44ef72015d..96446e88a1 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -29,6 +29,8 @@ "Башкы экран" "Экранды бөлүү" "%1$s колдонмосу жөнүндө маалымат" + + "Колдонмолорду сактап коюу" "%1$s | %2$s" "Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index f8ecb7eb9c..708a2f3562 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -29,6 +29,8 @@ "ໂຮມສະກຣີນ" "ແບ່ງໜ້າຈໍ" "ຂໍ້ມູນແອັບສຳລັບ %1$s" + + "ບັນທຶກຈັບຄູ່ແອັບ" "%1$s | %2$s" "ການຈັບຄູ່ແອັບນີ້ບໍ່ຮອງຮັບຢູ່ອຸປະກອນນີ້" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index b851d5539d..bc33bd8efd 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -29,6 +29,7 @@ "Pagrindinis" "Išskaidyto ekrano režimas" "Programos „%1$s“ informacija" + "„%1$s“ naudojimo nustatymai" "Išsaugoti programų porą" "%1$s | %2$s" "Ši programų pora šiame įrenginyje nepalaikoma" diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 2c1ec75e53..7dbe5facaa 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -29,6 +29,8 @@ "Sākums" "Sadalīt ekrānu" "%1$s: informācija par lietotni" + + "Saglabāt lietotņu pāri" "%1$s | %2$s" "Šis lietotņu pāris netiek atbalstīts šajā ierīcē" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index b87c2ce7c4..18849e9ce1 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -29,6 +29,8 @@ "Почетен екран" "Поделен екран" "Податоци за апликација за %1$s" + + "Зачувај го парот апликации" "%1$s | %2$s" "Паров апликации не е поддржан на уредов" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index beb2f6f8c8..529cc8d53e 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -29,6 +29,8 @@ "ഹോം" "സ്‌ക്രീൻ വിഭജന മോഡ്" "%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ" + + "ആപ്പ് ജോടി സംരക്ഷിക്കുക" "%1$s | %2$s" "ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 7b4bce7bf6..21c8ad15b2 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -29,6 +29,8 @@ "Нүүр" "Дэлгэцийг хуваах" "%1$s-н аппын мэдээлэл" + + "Апп хослуулалтыг хадгалах" "%1$s | %2$s" "Энэ апп хослуулалтыг уг төхөөрөмж дээр дэмждэггүй" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 8adb240021..1badd2124f 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -29,6 +29,7 @@ "होम" "स्प्लिट स्क्रीन" "%1$s साठी ॲपशी संबंधित माहिती" + "%1$s साठी वापरासंबंधित सेटिंग्ज" "ॲपची जोडी सेव्ह करा" "%1$s | %2$s" "या ॲपची जोडीला या डिव्हाइसवर सपोर्ट नाही" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index f194bc1483..270ebf0b68 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -29,6 +29,8 @@ "Rumah" "Skrin pisah" "Maklumat apl untuk %1$s" + + "Simpan gandingan apl" "%1$s | %2$s" "Gandingan apl ini tidak disokong pada peranti ini" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 7dc3b5ac11..cec9b1b76c 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -29,6 +29,7 @@ "ပင်မစာမျက်နှာ" "မျက်နှာပြင် ခွဲ၍ပြသခြင်း" "%1$s အတွက် အက်ပ်အချက်အလက်" + "%1$s အတွက် အသုံးပြုမှုဆက်တင်များ" "အက်ပ်တွဲချိတ်ခြင်း သိမ်းရန်" "%1$s | %2$s" "ဤအက်ပ်တွဲချိတ်ခြင်းကို ဤစက်တွင် ပံ့ပိုးမထားပါ" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 856ce9f260..392cf45721 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -29,6 +29,8 @@ "Startskjerm" "Delt skjerm" "Appinformasjon for %1$s" + + "Lagre apptilkoblingen" "%1$s | %2$s" "Denne apptilkoblingen støttes ikke på denne enheten" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 2197a8b6d2..f5a16ee257 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -29,6 +29,8 @@ "होम" "स्प्लिट स्क्रिन" "%1$s का हकमा एपसम्बन्धी जानकारी" + + "एपको पेयर सेभ गर्नुहोस्" "%1$s | %2$s" "यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index bd4508cf5d..176fbc9bc9 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -29,6 +29,8 @@ "Startscherm" "Gesplitst scherm" "App-info voor %1$s" + + "App-paar opslaan" "%1$s | %2$s" "Dit app-paar wordt niet ondersteund op dit apparaat" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index e2035a291d..db656a6a0f 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -29,6 +29,8 @@ "ହୋମ" "ସ୍କ୍ରିନ‌କୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ" "%1$s ପାଇଁ ଆପ ସୂଚନା" + + "ଆପ ପେୟାର ସେଭ କରନ୍ତୁ" "%1$s | %2$s" "ଏହି ଆପ ପେୟାର ଏ ଡିଭାଇସରେ ସମର୍ଥିତ ନୁହେଁ" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index f41282055b..a496865c3c 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -29,6 +29,8 @@ "ਮੁੱਖ ਪੰਨਾ" "ਸਪਲਿਟ ਸਕ੍ਰੀਨ" "%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ" + + "ਐਪ ਜੋੜਾਬੱਧ ਰੱਖਿਅਤ ਕਰੋ" "%1$s | %2$s" "ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਦਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਨ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ" @@ -125,7 +127,7 @@ "ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, %1$s ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ" "ਸੈਟਿੰਗਾਂ ਬਦਲੋ" "ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ" - "ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ" + "ਵਿਕਾਸਕਾਰ ਵਿਕਲਪ" "ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਐਪ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ" "ਨਵੀਆਂ ਐਪਾਂ ਲਈ" "ਅਗਿਆਤ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index a97d56e611..86a43ab666 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -29,6 +29,8 @@ "Ekran główny" "Podziel ekran" "Informacje o aplikacji: %1$s" + + "Zapisz parę aplikacji" "%1$s | %2$s" "Ta para aplikacji nie jest obsługiwana na tym urządzeniu" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 3257915e85..a8eadfe354 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -29,6 +29,7 @@ "Página inicial" "Ecrã dividido" "Informações da app para %1$s" + "Definições de utilização para %1$s" "Guardar par de apps" "%1$s | %2$s" "Este par de apps não é suportado neste dispositivo" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 27aa1ee861..2833a3fdb4 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -29,6 +29,8 @@ "Início" "Tela dividida" "Informações do app %1$s" + + "Salvar par de apps" "%1$s | %2$s" "Este Par de apps não está disponível no dispositivo" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 959bb1c792..a3ee56ee3f 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -29,6 +29,8 @@ "Pagina de pornire" "Ecran împărțit" "Informații despre aplicație pentru %1$s" + + "Salvează perechea de aplicații" "%1$s | %2$s" "Perechea de aplicații nu este acceptată pe acest dispozitiv" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 1844933ffd..7b99297f4a 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -29,6 +29,8 @@ "Главный экран" "Разделить экран" "Сведения о приложении \"%1$s\"" + + "Сохранить приложения" "%1$s | %2$s" "Одновременно использовать эти два приложения на устройстве нельзя." diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index d5a0114671..511d59348c 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -29,6 +29,8 @@ "මුල් පිටුව" "බෙදුම් තිරය" "%1$s සඳහා යෙදුම් තතු" + + "යෙදුම් යුගල සුරකින්න" "%1$s | %2$s" "මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 3d12a6513b..960259425e 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -29,6 +29,8 @@ "Domov" "Rozdeliť obrazovku" "Informácie o aplikácii pre %1$s" + + "Uložiť pár aplikácií" "%1$s | %2$s" "Tento pár aplikácií nie je v tomto zariadení podporovaný" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 070ccbbf86..2b334aa2eb 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -29,6 +29,7 @@ "Začetni zaslon" "Razdeljen zaslon" "Podatki o aplikaciji za: %1$s" + "Nastavitve uporabe za »%1$s«" "Shrani par aplikacij" "%1$s | %2$s" "Ta par aplikacij ni podprt v tej napravi" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index df2395ad10..fbeb20537d 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -29,6 +29,8 @@ "Ekrani bazë" "Ekrani i ndarë" "Informacioni i aplikacionit për %1$s" + + "Ruaj çiftin e aplikacioneve" "%1$s | %2$s" "Ky çift aplikacionesh nuk mbështetet në këtë pajisje" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 0721730178..8ae58ebb29 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -29,6 +29,7 @@ "Почетни екран" "Подељени екран" "Информације о апликацији за: %1$s" + "Подешавања потрошње за %1$s" "Сачувај пар апликација" "%1$s | %2$s" "Овај пар апликација није подржан на овом уређају" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 2b6a9aa3e0..d99fd86bbb 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -29,6 +29,8 @@ "Startskärm" "Delad skärm" "Appinformation för %1$s" + + "Spara app-par" "%1$s | %2$s" "De här apparna som ska användas tillsammans stöds inte på den här enheten" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index d44eb13972..8893a907cb 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -29,6 +29,8 @@ "Skrini ya kwanza" "Gawa skrini" "Maelezo ya programu ya %1$s" + + "Hifadhi jozi ya programu" "%1$s | %2$s" "Jozi hii ya programu haitumiki kwenye kifaa hiki" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index efa4b85959..fbd788071b 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -29,6 +29,8 @@ "முகப்பு" "திரைப் பிரிப்பு" "%1$sக்கான ஆப்ஸ் தகவல்கள்" + + "ஆப்ஸ் ஜோடியைச் சேமி" "%1$s | %2$s" "இந்தச் சாதனத்தில் இந்த ஆப்ஸ் ஜோடி ஆதரிக்கப்படவில்லை" @@ -84,8 +86,7 @@ "நிறுவல் நீக்கு" "ஆப்ஸ் தகவல்" "தனிப்பட்டதில் நிறுவு" - - + "ஆப்ஸை நிறுவல் நீக்கு" "நிறுவு" "பரிந்துரைக்காதே" "கணிக்கப்பட்ட ஆப்ஸைப் பின் செய்தல்" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index bd09562c41..11c2755cb9 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -29,6 +29,8 @@ "మొదటి ట్యాబ్" "స్ప్లిట్ స్క్రీన్" "%1$s కోసం యాప్ సమాచారం" + + "యాప్ పెయిర్‌ను సేవ్ చేయండి" "%1$s | %2$s" "ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు" @@ -124,7 +126,7 @@ "నోటిఫికేషన్ యాక్సెస్ అవసరం" "నోటిఫికేషన్ డాట్‌లను చూపించడానికి %1$sకు యాప్ నోటిఫికేషన్‌లను ఆన్ చేయండి" "సెట్టింగ్‌లను మార్చు" - "నోటిఫికేషన్ డాట్‌లను చూపు" + "నోటిఫికేషన్ డాట్‌లను చూపండి" "డెవలపర్ ఆప్షన్‌లు" "యాప్ చిహ్నాలను మొదటి స్క్రీన్‌కు జోడించండి" "కొత్త యాప్‌ల కోసం" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index dcaa17ba95..d006e5e117 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -29,6 +29,8 @@ "หน้าแรก" "แยกหน้าจอ" "ข้อมูลแอปสำหรับ %1$s" + + "บันทึกคู่แอป" "%1$s | %2$s" "ไม่รองรับคู่แอปนี้ในอุปกรณ์เครื่องนี้" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index ba4b6aaa21..a497d4f8d9 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -29,6 +29,8 @@ "Home" "Split screen" "Impormasyon ng app para sa %1$s" + + "I-save ang app pair" "%1$s | %2$s" "Hindi sinusuportahan sa device na ito ang pares ng app na ito" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index e46ffd1360..301a754379 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -29,6 +29,8 @@ "Ana ekran" "Bölünmüş ekran" "%1$s uygulama bilgileri" + + "Uygulama çiftini kaydedin" "%1$s | %2$s" "Bu uygulama çifti bu cihazda desteklenmiyor" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 9cca61f81f..3ff70b8b28 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -29,6 +29,8 @@ "Головний екран" "Розділити екран" "Інформація про додаток для %1$s" + + "Зберегти пару додатків" "%1$s | %2$s" "Ці два додатки не можна одночасно використовувати на цьому пристрої" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 5fbfc52d6a..653959ea7a 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -29,6 +29,8 @@ "ہوم" "اسپلٹ اسکرین" "‏%1$s کے لیے ایپ کی معلومات" + + "ایپس کے جوڑے کو محفوظ کریں" "%1$s | %2$s" "ایپس کا یہ جوڑا اس آلے پر تعاون یافتہ نہیں ہے" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 10e928b8b7..194822e789 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -29,6 +29,8 @@ "Bosh ekran" "Ekranni ikkiga ajratish" "%1$s ilovasi axboroti" + + "Ilova juftini saqlash" "%1$s | %2$s" "Bu ilova jufti ushbu qurilmada ishlamaydi" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 9eebdd757d..f50b8e8d9b 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -29,6 +29,8 @@ "Màn hình chính" "Chia đôi màn hình" "Thông tin ứng dụng cho %1$s" + + "Lưu cặp ứng dụng" "%1$s | %2$s" "Cặp ứng dụng này không hoạt động được trên thiết bị này" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 3c430c173b..b4c432b56a 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -29,6 +29,8 @@ "主屏幕" "分屏" "%1$s 的应用信息" + + "保存应用组合" "%1$s | %2$s" "在该设备上无法使用此应用对" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index ce26039325..94b3ae6eaa 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -29,6 +29,8 @@ "主畫面" "分割螢幕" "%1$s 的應用程式資料" + + "儲存應用程式配對" "%1$s | %2$s" "此裝置不支援此應用程式配對" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index fc0dddf161..e0b7ab2ea1 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -29,6 +29,8 @@ "主畫面" "分割畫面" "「%1$s」的應用程式資訊" + + "儲存應用程式配對" "%1$s | %2$s" "這部裝置不支援這組應用程式配對" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 147156447f..16d71a6da3 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -29,6 +29,8 @@ "Ikhaya" "Hlukanisa isikrini" "Ulwazi lwe-App ye-%1$s" + + "Londoloza i-app ebhangqiwe" "%1$s | %2$s" "Lokhu kubhanqwa kwe-app akusekelwa kule divayisi" @@ -123,7 +125,7 @@ "Valiwe" "Ukufinyelela izaziso kuyadingeka" "Ukuze ubonisa amcashazi esaziso, vula izaziso zohlelo lokusebenza ze-%1$s" - "Shintsha izilungiselelo" + "Shintsha amasethingi" "Bonisa amacashazi esaziso" "Izinketho zonjiniyela" "Engeza izithonjana ze-app kusikrini sasekhaya" From b748c8e6ee87bc65f2fc54e5a6fb4384e5be34ac Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 3 Jun 2024 18:20:44 -0700 Subject: [PATCH 043/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I7d47742f878876e358fec1130708bae36149f801 --- res/values-pa/strings.xml | 2 +- res/values-te/strings.xml | 2 +- res/values-zu/strings.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index f9042d3bf4..f1351c4332 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -125,7 +125,7 @@ "ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, %1$s ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ" "ਸੈਟਿੰਗਾਂ ਬਦਲੋ" "ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ" - "ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ" + "ਵਿਕਾਸਕਾਰ ਵਿਕਲਪ" "ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਐਪ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ" "ਨਵੀਆਂ ਐਪਾਂ ਲਈ" "ਅਗਿਆਤ" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 3cd412d46b..4c9de0439c 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -124,7 +124,7 @@ "నోటిఫికేషన్ యాక్సెస్ అవసరం" "నోటిఫికేషన్ డాట్‌లను చూపించడానికి %1$sకు యాప్ నోటిఫికేషన్‌లను ఆన్ చేయండి" "సెట్టింగ్‌లను మార్చు" - "నోటిఫికేషన్ డాట్‌లను చూపు" + "నోటిఫికేషన్ డాట్‌లను చూపండి" "డెవలపర్ ఆప్షన్‌లు" "యాప్ చిహ్నాలను మొదటి స్క్రీన్‌కు జోడించండి" "కొత్త యాప్‌ల కోసం" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index cbc0cb499b..675cfaf210 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -123,7 +123,7 @@ "Valiwe" "Ukufinyelela izaziso kuyadingeka" "Ukuze ubonisa amcashazi esaziso, vula izaziso zohlelo lokusebenza ze-%1$s" - "Shintsha izilungiselelo" + "Shintsha amasethingi" "Bonisa amacashazi esaziso" "Izinketho zonjiniyela" "Engeza izithonjana ze-app kusikrini sasekhaya" From 11afae1bc9320b7f583b720539690441ad9ab32f Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Fri, 31 May 2024 15:02:10 +0100 Subject: [PATCH 044/143] Adding logs to monitor OverviewCommandHelper This CL adds some logs to help analyzing why recents button with 3 button navigation sometimes don't open Overview. Bug: 337954957 Test: NONE Flag: EXEMPT Adding logs to debug issue Change-Id: I44a799319eca667b04d4e78a38ade796fc3b69fb --- .../quickstep/OverviewCommandHelper.java | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 3091e3dfc5..26a7c2f5bf 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -28,9 +28,11 @@ import android.content.Intent; import android.graphics.PointF; import android.os.SystemClock; import android.os.Trace; +import android.util.Log; import android.view.View; import androidx.annotation.BinderThread; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; @@ -58,6 +60,7 @@ import java.util.HashMap; * Helper class to handle various atomic commands for switching between Overview. */ public class OverviewCommandHelper { + private static final String TAG = "OverviewCommandHelper"; public static final int TYPE_SHOW = 1; public static final int TYPE_KEYBOARD_INPUT = 2; @@ -105,10 +108,19 @@ public class OverviewCommandHelper { * Called when the command finishes execution. */ private void scheduleNextTask(CommandInfo command) { - if (!mPendingCommands.isEmpty() && mPendingCommands.get(0) == command) { - mPendingCommands.remove(0); - executeNext(); + if (mPendingCommands.isEmpty()) { + Log.d(TAG, "no pending commands to schedule"); + return; } + if (mPendingCommands.get(0) != command) { + Log.d(TAG, "next task not scheduled." + + " mPendingCommands[0] type is " + mPendingCommands.get(0) + + " - command type is: " + command); + return; + } + Log.d(TAG, "scheduleNextTask called: " + command); + mPendingCommands.remove(0); + executeNext(); } /** @@ -119,10 +131,14 @@ public class OverviewCommandHelper { @UiThread private void executeNext() { if (mPendingCommands.isEmpty()) { + Log.d(TAG, "executeNext - mPendingCommands is empty"); return; } CommandInfo cmd = mPendingCommands.get(0); - if (executeCommand(cmd)) { + + boolean result = executeCommand(cmd); + Log.d(TAG, "executeNext cmd type: " + cmd + ", result: " + result); + if (result) { scheduleNextTask(cmd); } } @@ -144,14 +160,18 @@ public class OverviewCommandHelper { @BinderThread public void addCommand(int type) { if (mPendingCommands.size() >= MAX_QUEUE_SIZE) { + Log.d(TAG, "the pending command queue is full (" + mPendingCommands.size() + "). " + + "command not added: " + type); return; } + Log.d(TAG, "adding command type: " + type); CommandInfo cmd = new CommandInfo(type); MAIN_EXECUTOR.execute(() -> addCommand(cmd)); } @UiThread public void clearPendingCommands() { + Log.d(TAG, "clearing pending commands - size: " + mPendingCommands.size()); mPendingCommands.clear(); } @@ -182,9 +202,11 @@ public class OverviewCommandHelper { if (callbackList != null) { callbackList.add(() -> { + Log.d(TAG, "launching task callback: " + cmd); scheduleNextTask(cmd); mWaitForToggleCommandComplete = false; }); + Log.d(TAG, "launching task - waiting for callback: " + cmd); return false; } else { recents.startHome(); @@ -200,12 +222,17 @@ public class OverviewCommandHelper { private & RecentsViewContainer> boolean executeCommand( CommandInfo cmd) { if (mWaitForToggleCommandComplete && cmd.type == TYPE_TOGGLE) { + Log.d(TAG, "executeCommand: " + cmd + + " - waiting for toggle command complete"); return true; } BaseActivityInterface activityInterface = mOverviewComponentObserver.getActivityInterface(); RecentsView visibleRecentsView = activityInterface.getVisibleRecentsView(); RecentsView createdRecentsView; + + Log.d(TAG, "executeCommand: " + cmd + + " - visibleRecentsView: " + visibleRecentsView); if (visibleRecentsView == null) { T activity = activityInterface.getCreatedContainer(); createdRecentsView = activity == null ? null : activity.getOverviewPanel(); @@ -292,14 +319,17 @@ public class OverviewCommandHelper { updateRecentsViewFocus(cmd); logShowOverviewFrom(cmd.type); } + @Override public void onAnimationEnd(Animator animation) { + Log.d(TAG, "switching to Overview state - onAnimationEnd: " + cmd); super.onAnimationEnd(animation); onRecentsViewFocusUpdated(cmd); scheduleNextTask(cmd); } }; if (activityInterface.switchToRecentsIfVisible(animatorListener)) { + Log.d(TAG, "switching to Overview state - waiting: " + cmd); // If successfully switched, wait until animation finishes return false; } @@ -366,10 +396,12 @@ public class OverviewCommandHelper { cmd.mActiveCallbacks.addListener(recentAnimListener); } Trace.beginAsyncSection(TRANSITION_NAME, 0); + Log.d(TAG, "switching via recents animation - onGestureStarted: " + cmd); return false; } private void onTransitionComplete(CommandInfo cmd, AbsSwipeUpHandler handler) { + Log.d(TAG, "switching via recents animation - onTransitionComplete: " + cmd); cmd.removeListener(handler); Trace.endAsyncSection(TRANSITION_NAME, 0); onRecentsViewFocusUpdated(cmd); @@ -478,5 +510,15 @@ public class OverviewCommandHelper { mActiveCallbacks.removeListener(listener); } } + + @NonNull + @Override + public String toString() { + return "CommandInfo(" + + "type=" + type + ", " + + "createTime=" + createTime + ", " + + "mActiveCallbacks=" + mActiveCallbacks + + ")"; + } } } From 801563328a00778030c51e5d142c1c77d9c2a751 Mon Sep 17 00:00:00 2001 From: Uwais Ashraf Date: Tue, 4 Jun 2024 08:54:44 +0000 Subject: [PATCH 045/143] Allow DeviceProfile tests to run on TreeHugger Robolectric device Bug: 325088842 Test: Presubmit passes Flag: EXEMPT test-only Change-Id: Id2856b2016b2e1ba467c7b8e830631f5253d6b8c --- .../src/com/android/launcher3/AbstractDeviceProfileTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index e3787339b1..3405635426 100644 --- a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -57,7 +57,7 @@ import org.mockito.kotlin.whenever * * For an implementation that mocks InvariantDeviceProfile, use [FakeInvariantDeviceProfileTest] */ -@AllowedDevices(allowed = [DeviceProduct.CF_PHONE]) +@AllowedDevices(allowed = [DeviceProduct.CF_PHONE, DeviceProduct.HOST_SIDE_X86_64]) @IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD) abstract class AbstractDeviceProfileTest { protected val testContext: Context = InstrumentationRegistry.getInstrumentation().context From f895a7b0bddadb3be430ad2ed460cb5802515f69 Mon Sep 17 00:00:00 2001 From: Alina Zaidi Date: Tue, 28 May 2024 18:40:20 +0000 Subject: [PATCH 046/143] Add transition source for DesktopMode enter transition event originating from AppIcon press in overview Test: Updated unit tests Flag: EXEMPT not a major feature/ user visible change Bug: b/326231756 Change-Id: I9e53cd3ec41dd2475ba90ea8fab2fb7a90f5e158 --- .../desktop/DesktopRecentsTransitionController.kt | 5 +++-- .../com/android/quickstep/DesktopSystemShortcut.kt | 6 +++++- .../src/com/android/quickstep/SystemUiProxy.java | 5 +++-- .../src/com/android/quickstep/views/RecentsView.java | 9 ++++++--- .../android/quickstep/DesktopSystemShortcutTest.kt | 12 +++++++++--- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt index 3ef8e546e0..0000c0db2c 100644 --- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt +++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt @@ -30,6 +30,7 @@ import com.android.launcher3.util.Executors.MAIN_EXECUTOR import com.android.quickstep.SystemUiProxy import com.android.quickstep.TaskViewUtils import com.android.quickstep.views.DesktopTaskView +import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource import java.util.function.Consumer /** Manage recents related operations with desktop tasks */ @@ -57,8 +58,8 @@ class DesktopRecentsTransitionController( } /** Launch desktop tasks from recents view */ - fun moveToDesktop(taskId: Int) { - systemUiProxy.moveToDesktop(taskId) + fun moveToDesktop(taskId: Int, transitionSource: DesktopModeTransitionSource) { + systemUiProxy.moveToDesktop(taskId, transitionSource) } private class RemoteDesktopLaunchTransitionRunner( diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt index 50a06fcd75..9c188f31c3 100644 --- a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt +++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt @@ -24,6 +24,7 @@ import com.android.launcher3.popup.SystemShortcut import com.android.quickstep.views.RecentsView import com.android.quickstep.views.RecentsViewContainer import com.android.quickstep.views.TaskView.TaskContainer +import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.DesktopModeStatus /** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */ @@ -43,7 +44,10 @@ class DesktopSystemShortcut( override fun onClick(view: View) { dismissTaskMenuView() val recentsView = mTarget.getOverviewPanel>() - recentsView.moveTaskToDesktop(taskContainer) { + recentsView.moveTaskToDesktop( + taskContainer, + DesktopModeTransitionSource.APP_FROM_OVERVIEW + ) { mTarget.statsLogManager .logger() .withItemInfo(taskContainer.itemInfo) diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 0ac3ec7074..9c3fbaa25c 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -85,6 +85,7 @@ import com.android.wm.shell.back.IBackAnimation; import com.android.wm.shell.bubbles.IBubbles; import com.android.wm.shell.bubbles.IBubblesListener; import com.android.wm.shell.common.bubbles.BubbleBarLocation; +import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource; import com.android.wm.shell.common.pip.IPip; import com.android.wm.shell.common.pip.IPipAnimationListener; import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition; @@ -1494,10 +1495,10 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { } /** Call shell to move a task with given `taskId` to desktop */ - public void moveToDesktop(int taskId) { + public void moveToDesktop(int taskId, DesktopModeTransitionSource transitionSource) { if (mDesktopMode != null) { try { - mDesktopMode.moveToDesktop(taskId); + mDesktopMode.moveToDesktop(taskId, transitionSource); } catch (RemoteException e) { Log.w(TAG, "Failed call moveToDesktop", e); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4804e56844..9dfcd08e7e 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -217,6 +217,7 @@ import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; +import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource; import com.android.wm.shell.common.pip.IPipAnimationListener; import com.android.wm.shell.shared.DesktopModeStatus; @@ -6304,20 +6305,22 @@ public abstract class RecentsView finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false, - () -> moveTaskToDesktopInternal(taskContainer, successCallback))); + () -> moveTaskToDesktopInternal(taskContainer, successCallback, transitionSource))); } private void moveTaskToDesktopInternal(TaskContainer taskContainer, - Runnable successCallback) { + Runnable successCallback, DesktopModeTransitionSource transitionSource) { if (mDesktopRecentsTransitionController == null) { return; } - mDesktopRecentsTransitionController.moveToDesktop(taskContainer.getTask().key.id); + mDesktopRecentsTransitionController.moveToDesktop(taskContainer.getTask().key.id, + transitionSource); successCallback.run(); } diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt index 36f2ccf5be..50b5df13f2 100644 --- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt +++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt @@ -38,6 +38,7 @@ import com.android.quickstep.views.TaskViewIcon import com.android.systemui.shared.recents.model.Task import com.android.systemui.shared.recents.model.Task.TaskKey import com.android.window.flags.Flags +import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.DesktopModeStatus import com.google.common.truth.Truth.assertThat import org.junit.After @@ -152,8 +153,8 @@ class DesktopSystemShortcutTest { whenever(launcher.statsLogManager).thenReturn(statsLogManager) whenever(statsLogManager.logger()).thenReturn(statsLogger) whenever(statsLogger.withItemInfo(any())).thenReturn(statsLogger) - whenever(recentsView.moveTaskToDesktop(any(), any())).thenAnswer { - val successCallback = it.getArgument(1) + whenever(recentsView.moveTaskToDesktop(any(), any(), any())).thenAnswer { + val successCallback = it.getArgument(2) successCallback.run() } doReturn(workspaceItemInfo).whenever(taskContainer).itemInfo @@ -169,7 +170,12 @@ class DesktopSystemShortcutTest { val allTypesExceptRebindSafe = AbstractFloatingView.TYPE_ALL and AbstractFloatingView.TYPE_REBIND_SAFE.inv() verify(abstractFloatingViewHelper).closeOpenViews(launcher, true, allTypesExceptRebindSafe) - verify(recentsView).moveTaskToDesktop(eq(taskContainer), any()) + verify(recentsView) + .moveTaskToDesktop( + eq(taskContainer), + eq(DesktopModeTransitionSource.APP_FROM_OVERVIEW), + any() + ) verify(statsLogger).withItemInfo(workspaceItemInfo) verify(statsLogger).log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP) } From a3b66f59c2b1f7764bc0d8d8b24ee7db74322624 Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Tue, 4 Jun 2024 17:48:07 +0100 Subject: [PATCH 047/143] Fix split snapshot broken after rotating in fake orientation This CL replaces the live tile with the snapshot after rotating in fake orientation. The animateRotation function was created to extract the rotation logic to guarantee that switchToScreenshot call will only happen when there is a running task. Fix: 326410493 Flag: EXEMPT bug fix Test: Manual. Instructions in the bug description. Change-Id: I9d5e1b5ca803f8f8072702b37206a73b8d8a10ed --- .../com/android/quickstep/views/RecentsView.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4804e56844..a1cf6621d1 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2666,6 +2666,20 @@ public abstract class RecentsView { + animateRotation(newRotation); + finishRecentsAnimation(true /* toRecents */, false /* shouldPip */, + null /* onFinishComplete */); + }); + } + } + + private void animateRotation(int newRotation) { AnimatorSet pa = setRecentsChangedOrientation(true); pa.addListener(AnimatorListeners.forSuccessCallback(() -> { setLayoutRotation(newRotation, mOrientationState.getDisplayRotation()); @@ -5932,7 +5946,7 @@ public abstract class RecentsView Date: Thu, 23 May 2024 16:50:37 -0700 Subject: [PATCH 048/143] Consolidate the header views updating into a single method Call this updateView() in reset to ensure states are correct before animating. bug: 341053089 Test: manually - video: https://drive.google.com/file/d/18ZSAEplL1Lk5ij3IHlwtRh1GQ6GhrXX1/view?usp=sharing Flag: Aconfig com.android.launcher3.enable_private_space Nextfood Change-Id: I2c825a7fd7d9a5faad8fbbb70d0f40294f715a42 --- .../allapps/PrivateProfileManager.java | 123 +++++++----------- .../allapps/PrivateProfileManagerTest.java | 6 +- 2 files changed, 53 insertions(+), 76 deletions(-) diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index 32b5cfa32e..5cacf60615 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -20,7 +20,6 @@ import static android.view.View.GONE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; -import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PRIVATESPACE; import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN; import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ICON; import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER; @@ -207,15 +206,16 @@ public class PrivateProfileManager extends UserProfileManager { * when animation is not running. */ public void reset() { + // Ensure the state of the header views is what it should be before animating. + updateView(); getMainRecyclerView().setChildAttachedConsumer(null); int previousState = getCurrentState(); boolean isEnabled = !mAllApps.getAppsStore() .hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED); int updatedState = isEnabled ? STATE_ENABLED : STATE_DISABLED; setCurrentState(updatedState); - mFloatingMaskView = null; - if (mPSHeader != null) { - mPSHeader.setAlpha(1); + if (Flags.privateSpaceAddFloatingMaskView()) { + mFloatingMaskView = null; } // It's possible that previousState is 0 when reset is first called. mIsStateTransitioning = previousState != STATE_UNKNOWN && previousState != updatedState; @@ -224,7 +224,7 @@ public class PrivateProfileManager extends UserProfileManager { } else if (previousState == STATE_ENABLED && updatedState == STATE_DISABLED){ executeLock(); } - resetPrivateSpaceDecorator(updatedState); + addPrivateSpaceDecorator(updatedState); } /** Returns whether or not Private Space Settings Page is available. */ @@ -257,8 +257,9 @@ public class PrivateProfileManager extends UserProfileManager { setPrivateSpaceSettingsAvailable(apiWrapper.getPrivateSpaceSettingsIntent() != null); } + /** Adds a private space decorator only when STATE_ENABLED. */ @VisibleForTesting - void resetPrivateSpaceDecorator(int updatedState) { + void addPrivateSpaceDecorator(int updatedState) { ActivityAllAppsContainerView.AdapterHolder mainAdapterHolder = mAllApps.mAH.get(MAIN); if (updatedState == STATE_ENABLED) { // Create a new decorator instance if not already available. @@ -275,11 +276,6 @@ public class PrivateProfileManager extends UserProfileManager { } // Add Private Space Decorator to the Recycler view. mainAdapterHolder.mRecyclerView.addItemDecoration(mPrivateAppsSectionDecorator); - } else { - // Remove Private Space Decorator from the Recycler view. - if (mPrivateAppsSectionDecorator != null && !mIsAnimationRunning) { - mainAdapterHolder.mRecyclerView.removeItemDecoration(mPrivateAppsSectionDecorator); - } } } @@ -349,61 +345,57 @@ public class PrivateProfileManager extends UserProfileManager { // Ensure any unwanted animations to not happen. settingAndLockGroup.setLayoutTransition(null); } + updateView(); + } - //Add quietMode image and action for lock/unlock button - ViewGroup lockButton = mPSHeader.findViewById(R.id.ps_lock_unlock_button); - assert lockButton != null; - updateLockButton(lockButton); - - //Trigger lock/unlock action from header. - updateHeaderOnClickListener(mPSHeader); - - //Add image and action for private space settings button + /** Update the states of the views that make up the header at the state it is called in. */ + private void updateView() { + if (mPSHeader == null) { + return; + } + mPSHeader.setAlpha(1); + ViewGroup lockPill = mPSHeader.findViewById(R.id.ps_lock_unlock_button); + assert lockPill != null; + TextView lockText = lockPill.findViewById(R.id.lock_text); PrivateSpaceSettingsButton settingsButton = mPSHeader.findViewById(R.id.ps_settings_button); assert settingsButton != null; - updatePrivateSpaceSettingsButton(settingsButton); - //Add image for private space transitioning view - ImageView transitionView = parent.findViewById(R.id.ps_transition_image); + ImageView transitionView = mPSHeader.findViewById(R.id.ps_transition_image); assert transitionView != null; - updateTransitionImage(transitionView); - } - - /** - * Adds the quietModeButton and attach onClickListener for the header to animate different - * states when clicked. - */ - private void updateLockButton(ViewGroup lockButton) { - TextView lockText = lockButton.findViewById(R.id.lock_text); - switch (getCurrentState()) { + switch(getCurrentState()) { case STATE_ENABLED -> { + mPSHeader.setOnClickListener(null); + mPSHeader.setClickable(false); + // Remove header from accessibility target when enabled. + mPSHeader.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + lockText.setVisibility(VISIBLE); - lockButton.setVisibility(VISIBLE); - lockButton.setOnClickListener(view -> lockingAction(/* lock */ true)); - lockButton.setContentDescription(mUnLockedStateContentDesc); + lockPill.setVisibility(VISIBLE); + lockPill.setOnClickListener(view -> lockingAction(/* lock */ true)); + lockPill.setContentDescription(mUnLockedStateContentDesc); + + settingsButton.setVisibility(isPrivateSpaceSettingsAvailable() ? VISIBLE : GONE); + transitionView.setVisibility(GONE); } case STATE_DISABLED -> { - lockText.setVisibility(GONE); - lockButton.setVisibility(VISIBLE); - lockButton.setOnClickListener(view -> lockingAction(/* lock */ false)); - lockButton.setContentDescription(mLockedStateContentDesc); - } - default -> lockButton.setVisibility(GONE); - } - } + mPSHeader.setOnClickListener(view -> lockingAction(/* lock */ false)); + mPSHeader.setClickable(true); + // Add header as accessibility target when disabled. + mPSHeader.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + mPSHeader.setContentDescription(mLockedStateContentDesc); - private void updateHeaderOnClickListener(RelativeLayout header) { - if (getCurrentState() == STATE_DISABLED) { - header.setOnClickListener(view -> lockingAction(/* lock */ false)); - header.setClickable(true); - // Add header as accessibility target when disabled. - header.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); - header.setContentDescription(mLockedStateContentDesc); - } else { - header.setOnClickListener(null); - header.setClickable(false); - // Remove header from accessibility target when enabled. - header.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + lockText.setVisibility(GONE); + lockPill.setVisibility(VISIBLE); + lockPill.setOnClickListener(view -> lockingAction(/* lock */ false)); + lockPill.setContentDescription(mLockedStateContentDesc); + + settingsButton.setVisibility(GONE); + transitionView.setVisibility(GONE); + } + case STATE_TRANSITION -> { + transitionView.setVisibility(VISIBLE); + lockPill.setVisibility(GONE); + } } } @@ -413,23 +405,6 @@ public class PrivateProfileManager extends UserProfileManager { setQuietMode(lock); } - private void updatePrivateSpaceSettingsButton(PrivateSpaceSettingsButton settingsButton) { - if (getCurrentState() == STATE_ENABLED - && isPrivateSpaceSettingsAvailable()) { - settingsButton.setVisibility(VISIBLE); - } else { - settingsButton.setVisibility(GONE); - } - } - - private void updateTransitionImage(ImageView transitionImage) { - if (getCurrentState() == STATE_TRANSITION) { - transitionImage.setVisibility(VISIBLE); - } else { - transitionImage.setVisibility(GONE); - } - } - /** Finds the private space header to scroll to and set the private space icons to GONE. */ private void collapse() { AllAppsRecyclerView allAppsRecyclerView = mAllApps.getActiveRecyclerView(); @@ -644,6 +619,8 @@ public class PrivateProfileManager extends UserProfileManager { : LAUNCHER_PRIVATE_SPACE_LOCK_ANIMATION_END, mAllApps.getActiveRecyclerView()); if (!expand) { + mAllApps.mAH.get(MAIN).mRecyclerView.removeItemDecoration( + mPrivateAppsSectionDecorator); // Call onAppsUpdated() because it may be canceled when this animation occurs. mAllApps.getPersonalAppList().onAppsUpdated(); if (isPrivateSpaceHidden()) { diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java index 6ce1cb71fc..57117cb1c6 100644 --- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java +++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java @@ -149,7 +149,7 @@ public class PrivateProfileManagerTest { @Test public void quietModeFlagPresent_privateSpaceIsResetToDisabled() { PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); - doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt()); + doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt()); doNothing().when(privateProfileManager).executeLock(); doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView(); when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)) @@ -169,7 +169,7 @@ public class PrivateProfileManagerTest { @Test public void transitioningToUnlocked_resetCallsPostUnlock() throws Exception { PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); - doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt()); + doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt()); doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView(); when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)) .thenReturn(false); @@ -186,7 +186,7 @@ public class PrivateProfileManagerTest { @Test public void transitioningToLocked_resetCallsExecuteLock() throws Exception { PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); - doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt()); + doNothing().when(privateProfileManager).addPrivateSpaceDecorator(anyInt()); doNothing().when(privateProfileManager).executeLock(); doReturn(mAllAppsRecyclerView).when(privateProfileManager).getMainRecyclerView(); when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)) From 5580144d6b190577dbceef71358089457f19e48f Mon Sep 17 00:00:00 2001 From: Uwais Ashraf Date: Tue, 4 Jun 2024 17:27:59 +0000 Subject: [PATCH 049/143] Animate RecentsView when rotating in fake orientations Test: Manual - animations Bug: 336704871 Flag: EXEMPT bugfix Change-Id: I80629128a0730ca85d0313d15af806ddf840e82b --- .../src/com/android/quickstep/views/RecentsView.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4804e56844..c89b6b8ee7 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2675,17 +2675,9 @@ public abstract class RecentsView Date: Tue, 4 Jun 2024 19:05:42 +0000 Subject: [PATCH 050/143] Update AllSetActivity animations for certain device types This change updates the background animation at the All Set page for foldables of a certain dimension. Fix: 326231525 Fix: 335057950 Test: Run All Set page in multiple device types and observe the background animation Flag: EXEMPT bugfix Change-Id: I1197d689ab76f79a80d0be46ad96ada78666c214 --- quickstep/res/raw-h480dp/all_set_page_bg.json | 1 + quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json | 1 + 2 files changed, 2 insertions(+) create mode 100644 quickstep/res/raw-h480dp/all_set_page_bg.json create mode 100644 quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json diff --git a/quickstep/res/raw-h480dp/all_set_page_bg.json b/quickstep/res/raw-h480dp/all_set_page_bg.json new file mode 100644 index 0000000000..f2998a038a --- /dev/null +++ b/quickstep/res/raw-h480dp/all_set_page_bg.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":701,"h":841,"nm":"SUW_WelcomeScreen_FoldableOpen_Portrait_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[55]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.949},"o":{"x":0.167,"y":0.167},"t":0,"s":[181.172,148.425,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.038},"t":95,"s":[181.172,-68.377,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[181.172,148.425,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[21.6,21.6,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":9.3,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.619]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.263]},"t":95,"s":[82]},{"t":180,"s":[67]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.927]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[458.803]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.05]},"t":95,"s":[536.803]},{"t":180,"s":[458.803]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[707.143]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.069]},"t":95,"s":[639.643]},{"t":180,"s":[707.143]}],"ix":4}},"a":{"k":[{"s":[164.438,1433.781,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[164.438,1433.781,0],"t":180,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"a":0,"k":[-30,30,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2361.125,4541.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[350.5,420.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[420.5,-350.5],[-420.5,-350.5],[-420.5,350.5],[420.5,350.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json b/quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json new file mode 100644 index 0000000000..ae1b5604e5 --- /dev/null +++ b/quickstep/res/raw-w840dp-h480dp/all_set_page_bg.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":181,"w":841,"h":701,"nm":"SUW_WelcomeScreen_FelixOpen_Dynamic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary","cl":"primary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":180,"s":[55]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.07,"y":0.939},"o":{"x":0.167,"y":0.167},"t":0,"s":[140.975,228.318,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.773,"y":0.045},"t":95,"s":[140.975,47.65,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[140.975,228.318,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-3514.717,-358.642,0],"ix":1,"l":2},"s":{"a":0,"k":[18,18,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[100.594,-128.921],[118.85,-93.491],[148.984,-67.406],[148.684,-27.55],[163.244,9.552],[144.457,44.702],[140.106,84.321],[107.136,106.715],[84.872,139.773],[45.271,144.279],[10.194,163.205],[-26.964,148.792],[-66.818,149.249],[-93.023,119.218],[-128.524,101.101],[-137.771,62.332],[-160.786,29.793],[-150.957,-8.833],[-156.215,-48.341],[-129.561,-77.974],[-115.856,-115.401],[-78.484,-129.253],[-48.956,-156.023],[-9.427,-150.921],[29.159,-160.903],[61.789,-138.015]],"o":[[-100.594,128.921],[-118.85,93.491],[-148.984,67.406],[-148.684,27.55],[-163.244,-9.552],[-144.456,-44.702],[-140.106,-84.321],[-107.136,-106.715],[-84.872,-139.773],[-45.271,-144.279],[-10.194,-163.205],[26.964,-148.792],[66.818,-149.249],[93.023,-119.218],[128.524,-101.101],[137.771,-62.332],[160.786,-29.793],[150.957,8.833],[156.215,48.341],[129.561,77.974],[115.856,115.4],[78.484,129.253],[48.956,156.023],[9.427,150.921],[-29.159,160.903],[-61.789,138.015]],"v":[[975.226,761.299],[707.165,899.424],[509.8,1127.42],[208.253,1125.148],[-72.46,1235.308],[-338.41,1093.162],[-638.164,1060.25],[-807.592,810.792],[-1057.715,642.348],[-1091.808,342.727],[-1235.002,77.338],[-1125.948,-203.807],[-1129.407,-505.342],[-902.191,-703.604],[-765.123,-972.207],[-471.796,-1042.166],[-225.603,-1216.305],[66.637,-1141.935],[365.557,-1181.715],[589.761,-980.053],[872.928,-876.361],[977.734,-593.606],[1180.277,-370.197],[1141.675,-71.124],[1217.196,220.821],[1044.029,467.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[-3509.952,-363.731],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Polystar 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.713725490196,0.556862745098,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[11.111],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[11.111],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".tertiary","cl":"tertiary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.619]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[67]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.263]},"t":95,"s":[82]},{"t":180,"s":[67]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.07],"y":[0.913]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[639]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[-0.06]},"t":95,"s":[704]},{"t":180,"s":[639]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.07],"y":[1.12]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[527.25]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.719],"y":[0.083]},"t":95,"s":[471]},{"t":180,"s":[527.25]}],"ix":4}},"a":{"k":[{"s":[164.438,1433.781,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[164.438,1433.781,0],"t":180,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"a":0,"k":[-25,25,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2361.125,4541.989],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[164.438,1481.781],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.901960784314,0.764705882353,0.423529411765,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[6],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[6],"t":180,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":181,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[420.5,350.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[420.5,-350.5],[-420.5,-350.5],[-420.5,350.5],[420.5,350.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":181,"st":0,"bm":0}],"markers":[]} \ No newline at end of file From 6c76501e0e615bf52b4a384f57512925a7bba1ae Mon Sep 17 00:00:00 2001 From: Xiaowen Lei Date: Tue, 4 Jun 2024 10:30:02 -0700 Subject: [PATCH 051/143] Don't add padding for Smartspace (actual and preview). As demonstrated in ag/27287153, the actual Smartspace doesn't have any top padding, but the qsb_preview does. - Turns out, ShortcutAndWidgetContainer sets padding on its children. - The actual Smartspace has padding removed by overriding the `setPadding` method in SmartspaceViewContainer. (See ag/13562740.) This CL updates ShortcutAndWidgetContainer.java to not add padding for either the actual or the preview Smartspace. It makes use of `R.id.search_container_workspace` to identify the applicable cases, rather than checking class types or names. This way, there is no Pixel-specific logic added. Before: https://hsv.googleplex.com/6335187293044736?node=18 After: https://hsv.googleplex.com/5450651931770880?node=18 Actual Smartspace, for reference: - https://hsv.googleplex.com/6083634648842240?node=14 Note the `isChildQsb` also returns true for the QsbContainerView. Since that class already has the same `setPadding` override: - https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/src/com/android/launcher3/qsb/QsbContainerView.java;l=147-150;drc=e58aaf1802e43f73bbd417658c1c4c42e2fe28fd This CL does't affect its padding. Flag: EXEMPT bugfix Bug: 338601960 Test: Go to Wallpaper & style preview for Home screen. Change-Id: I5b6f7752cfee556b815c83e9df85f9e74f23ab4b --- .../android/launcher3/ShortcutAndWidgetContainer.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java index b22b690260..7484b64829 100644 --- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java +++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java @@ -158,6 +158,11 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon. final PointF appWidgetScale = dp.getAppWidgetScale((ItemInfo) child.getTag()); lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY, appWidgetScale.x, appWidgetScale.y, mBorderSpace, dp.widgetPadding); + } else if (isChildQsb(child)) { + lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY, + mBorderSpace); + // No need to add padding for Qsb, which is either Smartspace (actual or preview), or + // QsbContainerView. } else { lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY, mBorderSpace); @@ -185,6 +190,10 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon. child.measure(childWidthMeasureSpec, childheightMeasureSpec); } + private boolean isChildQsb(View child) { + return child.getId() == R.id.search_container_workspace; + } + public boolean invertLayoutHorizontally() { return mInvertIfRtl && Utilities.isRtl(getResources()); } From 05e963c245dfede778ddab90c357e20bdd5ea3f1 Mon Sep 17 00:00:00 2001 From: Brandon Dayauon Date: Tue, 4 Jun 2024 17:23:43 -0700 Subject: [PATCH 052/143] Make private profile header scrollable bug: 345007467 Test: manually video: before: https://drive.google.com/file/d/1XzpD-R48WRKFBeDlHXU5xSGgc50ZON8o/view?usp=sharing after: https://drive.google.com/file/d/1VBKZluzxvpP8ucs_uylk5esRlm9KzrZb/view?usp=sharing Flag: Aconfig com.android.launcher3.enable_private_space Nextfood Change-Id: I1db4bdf244b37b4c4cf55cb0d70d4011fee7de90 --- src/com/android/launcher3/allapps/AlphabeticalAppsList.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index a8103317cd..5d03a93254 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -337,6 +337,8 @@ public class AlphabeticalAppsList implement && !mPrivateApps.isEmpty()) { // Always add PS Header if Space is present and visible. position = mPrivateProviderManager.addPrivateSpaceHeader(mAdapterItems); + mFastScrollerSections.add(new FastScrollSectionInfo( + mPrivateProfileAppScrollerBadge, position)); int privateSpaceState = mPrivateProviderManager.getCurrentState(); switch (privateSpaceState) { case PrivateProfileManager.STATE_DISABLED: From 481e3ae079282a297d2d6465a5427e7f288e8712 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Tue, 4 Jun 2024 16:24:21 +0100 Subject: [PATCH 053/143] Fix icon and DWB toast focus transition - icon and DWB toast now transition in with animation when swipe up from apps to Overview - Refacotred focusTransition into MultiProperty, with separate control from fullScreenProgress and scaleAndDim, and get rid of "invert" parameter and iconScaleAnimStartProgress variable which is very confusing - Added a SCALE_AND_DIM_OUT property for use with PendingAnmation during dismiss, as PendingAnimation does not support per animator interpolator - Use height from resource in DWB toast when calcualting translation, so translation can be properly set before view is measured - Always set bannerOffsetPercentage regardless if banner is added Fix: 344786723 Fix: 315972057 Fix: 313644427 Flag: EXEMPT bugfix Test: Quick switch from home, icon and DWB toast don't transition in until gesture release Test: Quick switch from app, icon and DWB toast don't transition in until gesture release to Overview Test: Dismiss focus task, icon and DWB toast transition in after transition settle Test: Swipe down task, icon and DWB toast transition out with finger Test: Launcher central task, icon and DWB toast transition out Change-Id: Ie16a2ceff10967de38b5f66c52f4be00d0051c5f --- .../res/layout/digital_wellbeing_toast.xml | 2 +- quickstep/res/values/dimens.xml | 3 + .../views/DigitalWellBeingToast.java | 14 ++- .../android/quickstep/views/RecentsView.java | 3 +- .../com/android/quickstep/views/TaskView.kt | 116 +++++++++++++----- 5 files changed, 97 insertions(+), 41 deletions(-) diff --git a/quickstep/res/layout/digital_wellbeing_toast.xml b/quickstep/res/layout/digital_wellbeing_toast.xml index 42cddbfa0d..9144c7f9f7 100644 --- a/quickstep/res/layout/digital_wellbeing_toast.xml +++ b/quickstep/res/layout/digital_wellbeing_toast.xml @@ -19,7 +19,7 @@ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" style="@style/TextTitle" android:layout_width="match_parent" - android:layout_height="48dp" + android:layout_height="@dimen/digital_wellbeing_toast_height" android:background="@drawable/bg_wellbeing_toast" android:forceHasOverlappingRendering="false" android:gravity="center" diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 08d36d8d87..6bbf7f66ef 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -487,4 +487,7 @@ 24dp 8dp + + 48dp + diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java index 6377bf4ded..4a5b9e4cc1 100644 --- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -90,6 +90,8 @@ public final class DigitalWellBeingToast { private final TaskView mTaskView; private final LauncherApps mLauncherApps; + private final int mBannerHeight; + private Task mTask; private boolean mHasLimit; @@ -109,6 +111,8 @@ public final class DigitalWellBeingToast { mContainer = container; mTaskView = taskView; mLauncherApps = container.asContext().getSystemService(LauncherApps.class); + mBannerHeight = container.asContext().getResources().getDimensionPixelSize( + R.dimen.digital_wellbeing_toast_height); } private void setNoLimit() { @@ -359,10 +363,12 @@ public final class DigitalWellBeingToast { } void updateBannerOffset(float offsetPercentage) { - if (mBanner != null && mBannerOffsetPercentage != offsetPercentage) { + if (mBannerOffsetPercentage != offsetPercentage) { mBannerOffsetPercentage = offsetPercentage; - updateTranslationY(); - mBanner.invalidateOutline(); + if (mBanner != null) { + updateTranslationY(); + mBanner.invalidateOutline(); + } } } @@ -372,7 +378,7 @@ public final class DigitalWellBeingToast { } mBanner.setTranslationY( - (mBannerOffsetPercentage * mBanner.getHeight()) + mSplitOffsetTranslationY); + (mBannerOffsetPercentage * mBannerHeight) + mSplitOffsetTranslationY); } private void updateTranslationX() { diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4804e56844..e116e87f34 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2955,7 +2955,6 @@ public abstract class RecentsView x * y }, + 1f + ) + private val focusTransitionFullscreen = + focusTransitionPropertyFactory.get(FOCUS_TRANSITION_INDEX_FULLSCREEN) + private val focusTransitionScaleAndDim = + focusTransitionPropertyFactory.get(FOCUS_TRANSITION_INDEX_SCALE_AND_DIM) + /** + * Variant of [focusTransitionScaleAndDim] that has a built-in interpolator, to be used with + * [com.android.launcher3.anim.PendingAnimation] via [SCALE_AND_DIM_OUT] only. PendingAnimation + * doesn't support interpolator per animation, so we'll have to interpolate inside the property. + */ + private var focusTransitionScaleAndDimOut = focusTransitionScaleAndDim.value + set(value) { + field = value + focusTransitionScaleAndDim.value = + FOCUS_TRANSITION_FAST_OUT_INTERPOLATOR.getInterpolation(field) + } private var iconAndDimAnimator: ObjectAnimator? = null // The current background requests to load the task thumbnail and icon @@ -1301,43 +1337,23 @@ constructor( } } - protected open fun setIconsAndBannersFullscreenProgress(progress: Float) { - // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are - // oversized and banner would look disproportionately large. - if (recentsView?.stateManager?.state == LauncherState.BACKGROUND_APP) { - return - } - setIconsAndBannersTransitionProgress(progress, invert = true) - } - /** * Called to animate a smooth transition when going directly from an app into Overview (and vice * versa). Icons fade in, and DWB banners slide in with a "shift up" animation. */ - protected open fun setIconsAndBannersTransitionProgress(progress: Float, invert: Boolean) { - focusTransitionProgress = if (invert) 1 - progress else progress - getIconContentScale(invert).let { iconContentScale -> - taskContainers.forEach { - it.iconView.setContentAlpha(iconContentScale) - it.digitalWellBeingToast?.updateBannerOffset(1f - iconContentScale) - } + private fun onFocusTransitionProgressUpdated(focusTransitionProgress: Float) { + taskContainers.forEach { + it.iconView.setContentAlpha(focusTransitionProgress) + it.digitalWellBeingToast?.updateBannerOffset(1f - focusTransitionProgress) } } - private fun getIconContentScale(invert: Boolean): Float { - val iconScalePercentage = SCALE_ICON_DURATION.toFloat() / DIM_ANIM_DURATION - val lowerClamp = if (invert) 1f - iconScalePercentage else 0f - val upperClamp = if (invert) 1f else iconScalePercentage - return Interpolators.clampToProgress(Interpolators.FAST_OUT_SLOW_IN, lowerClamp, upperClamp) - .getInterpolation(focusTransitionProgress) - } - fun animateIconScaleAndDimIntoView() { iconAndDimAnimator?.cancel() iconAndDimAnimator = - ObjectAnimator.ofFloat(this, FOCUS_TRANSITION, 1f).apply { - setCurrentFraction(iconScaleAnimStartProgress) - setDuration(DIM_ANIM_DURATION).interpolator = Interpolators.LINEAR + ObjectAnimator.ofFloat(focusTransitionScaleAndDim, MULTI_PROPERTY_VALUE, 0f, 1f).apply { + duration = SCALE_ICON_DURATION + interpolator = Interpolators.LINEAR addListener( object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { @@ -1351,7 +1367,7 @@ constructor( fun setIconScaleAndDim(iconScale: Float) { iconAndDimAnimator?.cancel() - setIconsAndBannersTransitionProgress(iconScale, invert = false) + focusTransitionScaleAndDim.value = iconScale } /** Set a color tint on the snapshot and supporting views. */ @@ -1454,7 +1470,8 @@ constructor( it.iconView.setVisibility(if (fullscreenProgress < 1) VISIBLE else INVISIBLE) it.overlay.setFullscreenProgress(fullscreenProgress) } - setIconsAndBannersFullscreenProgress(fullscreenProgress) + focusTransitionFullscreen.value = + FOCUS_TRANSITION_FAST_OUT_INTERPOLATOR.getInterpolation(1 - fullscreenProgress) updateSnapshotRadius() } @@ -1638,21 +1655,43 @@ constructor( const val FLAG_UPDATE_ALL = (FLAG_UPDATE_ICON or FLAG_UPDATE_THUMBNAIL or FLAG_UPDATE_CORNER_RADIUS) + const val FOCUS_TRANSITION_INDEX_FULLSCREEN = 0 + const val FOCUS_TRANSITION_INDEX_SCALE_AND_DIM = 1 + const val FOCUS_TRANSITION_INDEX_COUNT = 2 + /** The maximum amount that a task view can be scrimmed, dimmed or tinted. */ const val MAX_PAGE_SCRIM_ALPHA = 0.4f const val SCALE_ICON_DURATION: Long = 120 private const val DIM_ANIM_DURATION: Long = 700 + private const val FOCUS_TRANSITION_THRESHOLD = + SCALE_ICON_DURATION.toFloat() / DIM_ANIM_DURATION + val FOCUS_TRANSITION_FAST_OUT_INTERPOLATOR = + Interpolators.clampToProgress( + Interpolators.FAST_OUT_SLOW_IN, + 1f - FOCUS_TRANSITION_THRESHOLD, + 1f + )!! private val SYSTEM_GESTURE_EXCLUSION_RECT = listOf(Rect()) - @JvmField - val FOCUS_TRANSITION: FloatProperty = + private val FOCUS_TRANSITION: FloatProperty = object : FloatProperty("focusTransition") { override fun setValue(taskView: TaskView, v: Float) { - taskView.setIconsAndBannersTransitionProgress(v, false /* invert */) + taskView.focusTransitionProgress = v } override fun get(taskView: TaskView) = taskView.focusTransitionProgress } + + @JvmField + val SCALE_AND_DIM_OUT: FloatProperty = + object : FloatProperty("scaleAndDimFastOut") { + override fun setValue(taskView: TaskView, v: Float) { + taskView.focusTransitionScaleAndDimOut = v + } + + override fun get(taskView: TaskView) = taskView.focusTransitionScaleAndDimOut + } + private val SPLIT_SELECT_TRANSLATION_X: FloatProperty = object : FloatProperty("splitSelectTranslationX") { override fun setValue(taskView: TaskView, v: Float) { @@ -1661,6 +1700,7 @@ constructor( override fun get(taskView: TaskView) = taskView.splitSelectTranslationX } + private val SPLIT_SELECT_TRANSLATION_Y: FloatProperty = object : FloatProperty("splitSelectTranslationY") { override fun setValue(taskView: TaskView, v: Float) { @@ -1669,6 +1709,7 @@ constructor( override fun get(taskView: TaskView) = taskView.splitSelectTranslationY } + private val DISMISS_TRANSLATION_X: FloatProperty = object : FloatProperty("dismissTranslationX") { override fun setValue(taskView: TaskView, v: Float) { @@ -1677,6 +1718,7 @@ constructor( override fun get(taskView: TaskView) = taskView.dismissTranslationX } + private val DISMISS_TRANSLATION_Y: FloatProperty = object : FloatProperty("dismissTranslationY") { override fun setValue(taskView: TaskView, v: Float) { @@ -1685,6 +1727,7 @@ constructor( override fun get(taskView: TaskView) = taskView.dismissTranslationY } + private val TASK_OFFSET_TRANSLATION_X: FloatProperty = object : FloatProperty("taskOffsetTranslationX") { override fun setValue(taskView: TaskView, v: Float) { @@ -1693,6 +1736,7 @@ constructor( override fun get(taskView: TaskView) = taskView.taskOffsetTranslationX } + private val TASK_OFFSET_TRANSLATION_Y: FloatProperty = object : FloatProperty("taskOffsetTranslationY") { override fun setValue(taskView: TaskView, v: Float) { @@ -1701,6 +1745,7 @@ constructor( override fun get(taskView: TaskView) = taskView.taskOffsetTranslationY } + private val TASK_RESISTANCE_TRANSLATION_X: FloatProperty = object : FloatProperty("taskResistanceTranslationX") { override fun setValue(taskView: TaskView, v: Float) { @@ -1709,6 +1754,7 @@ constructor( override fun get(taskView: TaskView) = taskView.taskResistanceTranslationX } + private val TASK_RESISTANCE_TRANSLATION_Y: FloatProperty = object : FloatProperty("taskResistanceTranslationY") { override fun setValue(taskView: TaskView, v: Float) { @@ -1717,6 +1763,7 @@ constructor( override fun get(taskView: TaskView) = taskView.taskResistanceTranslationY } + @JvmField val GRID_END_TRANSLATION_X: FloatProperty = object : FloatProperty("gridEndTranslationX") { @@ -1726,6 +1773,7 @@ constructor( override fun get(taskView: TaskView) = taskView.gridEndTranslationX } + @JvmField val DISMISS_SCALE: FloatProperty = object : FloatProperty("dismissScale") { From 0f6668d01190d56d3d3a7b6e1aca71dec0b836c2 Mon Sep 17 00:00:00 2001 From: Luca Zuccarini Date: Thu, 30 May 2024 12:16:27 +0000 Subject: [PATCH 054/143] Miscellaneous polish for new home animation. 1. Update the starting window velocity when coming from 3-button nav or predictive back Before we used an arbitrary fixed velocity which goes down to basically 0 with the old implementation, but caused a noticeable jump up in the new one when using predictive back. Now we just pass 0, since the predictive back framework doesn't give us the actual velocity. 2. Add the scaling home reveal to the targetless (not going back to a specific app icon or widget) animation and 3-button nav Bug: 298089923 Fix: 343143876 Flag: com.android.launcher3.enable_scaling_reveal_home_animation Test: manually tested with flag on and off Change-Id: Ied3630a51862731fad044b68f76a45dc87f2e17b --- .../launcher3/QuickstepTransitionManager.java | 26 ++++++++++---- .../quickstep/LauncherSwipeHandlerV2.java | 34 +++++++++++++------ .../quickstep/util/RectFSpringAnim.java | 4 +++ .../util/ScalingWorkspaceRevealAnim.kt | 7 +++- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 0c499b8bc6..fae281a70a 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -151,6 +151,7 @@ import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.RectFSpringAnim.DefaultSpringConfig; import com.android.quickstep.util.RectFSpringAnim.TaskbarHotseatSpringConfig; +import com.android.quickstep.util.ScalingWorkspaceRevealAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.util.SurfaceTransaction; import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties; @@ -174,7 +175,6 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map.Entry; /** * Manages the opening and closing app transitions from Launcher @@ -1630,10 +1630,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets)); } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get() && !playFallBackAnimation) { - // Use a fixed velocity to start the animation. - float velocityPxPerS = DynamicResource.provider(mLauncher) - .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s); - PointF velocity = new PointF(0, -velocityPxPerS); + PointF velocity; + if (enableScalingRevealHomeAnimation()) { + velocity = new PointF(); + } else { + // Use a fixed velocity to start the animation. + float velocityPxPerS = DynamicResource.provider(mLauncher) + .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s); + velocity = new PointF(0, -velocityPxPerS); + } rectFSpringAnim = getClosingWindowAnimators( anim, appTargets, launcherView, velocity, startRect, startWindowCornerRadius); @@ -1642,8 +1647,15 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener // layout bounds. skipAllAppsScale = true; } else if (!fromPredictiveBack) { - anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y, - true /* animateOverviewScrim */, launcherView).getAnimators()); + if (enableScalingRevealHomeAnimation()) { + anim.play( + new ScalingWorkspaceRevealAnim( + mLauncher, rectFSpringAnim, + rectFSpringAnim.getTargetRect()).getAnimators()); + } else { + anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y, + true /* animateOverviewScrim */, launcherView).getAnimators()); + } if (!areAllTargetsTranslucent(appTargets)) { anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController().stateDepth, diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java index 080e03acc2..3c665906b5 100644 --- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java +++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java @@ -173,14 +173,10 @@ public class LauncherSwipeHandlerV2 extends } @Override - public void playAtomicAnimation(float velocity) { - if (enableScalingRevealHomeAnimation()) { - if (mContainer != null) { - new ScalingWorkspaceRevealAnim( - mContainer, mSiblingAnimation, getWindowTargetRect()).start(); - } - } else { - super.playAtomicAnimation(velocity); + protected void playScalingRevealAnimation() { + if (mContainer != null) { + new ScalingWorkspaceRevealAnim(mContainer, mSiblingAnimation, + getWindowTargetRect()).start(); } } @@ -370,9 +366,25 @@ public class LauncherSwipeHandlerV2 extends @Override public void playAtomicAnimation(float velocity) { - new StaggeredWorkspaceAnim(mContainer, velocity, true /* animateOverviewScrim */, - getViewIgnoredInWorkspaceRevealAnimation()) - .start(); + if (enableScalingRevealHomeAnimation()) { + playScalingRevealAnimation(); + } else { + new StaggeredWorkspaceAnim(mContainer, velocity, true /* animateOverviewScrim */, + getViewIgnoredInWorkspaceRevealAnimation()) + .start(); + } + } + + /** + * Extracted in a different method so subclasses that have a custom window animation with a + * target (icons, widgets) can pass the optional parameters. + */ + protected void playScalingRevealAnimation() { + if (mContainer != null) { + new ScalingWorkspaceRevealAnim( + mContainer, null /* siblingAnimation */, + null /* windowTargetRect */).start(); + } } } } diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java index 769ccc092b..00b40116f7 100644 --- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java +++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java @@ -157,6 +157,10 @@ public class RectFSpringAnim extends ReleaseCheck { mCurrentY = getTrackedYFromRect(mStartRect); } + public RectF getTargetRect() { + return mTargetRect; + } + private float getTrackedYFromRect(RectF rect) { switch (mTracking) { case TRACKING_TOP: diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt index 4513fa295d..f547a7fba1 100644 --- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt +++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt @@ -16,6 +16,7 @@ package com.android.quickstep.util +import android.animation.AnimatorSet import android.graphics.Matrix import android.graphics.Path import android.graphics.RectF @@ -187,7 +188,11 @@ class ScalingWorkspaceRevealAnim( ) } + fun getAnimators(): AnimatorSet { + return animation.buildAnim() + } + fun start() { - animation.buildAnim().start() + getAnimators().start() } } From 86b9ad4ff7097b8e8891e7915c19ab30adfa1f51 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Fri, 31 May 2024 16:36:29 -0400 Subject: [PATCH 055/143] Add debug logs to TopTaskTracker Flag: NONE debug logs Bug: 342247547 Test: checked TIS logs Change-Id: I6c8440af122a0376ffd77df6c8c9b9aeb742d447 --- .../com/android/quickstep/TopTaskTracker.java | 53 +++++++++++++++++++ .../quickstep/TouchInteractionService.java | 1 + .../util/SplitConfigurationOptions.java | 6 +++ 3 files changed, 60 insertions(+) diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java index 3a6b8042cd..29c80fd066 100644 --- a/quickstep/src/com/android/quickstep/TopTaskTracker.java +++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java @@ -28,6 +28,7 @@ import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITIO import android.annotation.UserIdInt; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -47,6 +48,7 @@ import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; import com.android.wm.shell.splitscreen.ISplitScreenListener; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -61,6 +63,10 @@ import java.util.List; public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskStackChangeListener, SafeCloseable { + private static final String TAG = "TopTaskTracker"; + + private static final boolean DEBUG = true; + public static MainThreadInitializedObject INSTANCE = new MainThreadInitializedObject<>(TopTaskTracker::new); @@ -92,10 +98,19 @@ public class TopTaskTracker extends ISplitScreenListener.Stub @Override public void onTaskRemoved(int taskId) { mOrderedTaskList.removeIf(rto -> rto.taskId == taskId); + if (DEBUG) { + Log.i(TAG, "onTaskRemoved: taskId=" + taskId); + } } @Override public void onTaskMovedToFront(RunningTaskInfo taskInfo) { + if (!mOrderedTaskList.isEmpty() + && mOrderedTaskList.getFirst().taskId != taskInfo.taskId + && DEBUG) { + Log.i(TAG, "onTaskMovedToFront: (moved taskInfo to front) taskId=" + taskInfo.taskId + + ", baseIntent=" + taskInfo.baseIntent); + } mOrderedTaskList.removeIf(rto -> rto.taskId == taskInfo.taskId); mOrderedTaskList.addFirst(taskInfo); @@ -106,6 +121,11 @@ public class TopTaskTracker extends ISplitScreenListener.Stub final RunningTaskInfo topTaskOnHomeDisplay = mOrderedTaskList.stream() .filter(rto -> rto.displayId == DEFAULT_DISPLAY).findFirst().orElse(null); if (topTaskOnHomeDisplay != null) { + if (DEBUG) { + Log.i(TAG, "onTaskMovedToFront: (removing top task on home display) taskId=" + + topTaskOnHomeDisplay.taskId + + ", baseIntent=" + topTaskOnHomeDisplay.baseIntent); + } mOrderedTaskList.removeIf(rto -> rto.taskId == topTaskOnHomeDisplay.taskId); mOrderedTaskList.addFirst(topTaskOnHomeDisplay); } @@ -119,6 +139,10 @@ public class TopTaskTracker extends ISplitScreenListener.Stub if (info.taskId != taskInfo.taskId && info.taskId != mMainStagePosition.taskId && info.taskId != mSideStagePosition.taskId) { + if (DEBUG) { + Log.i(TAG, "onTaskMovedToFront: (removing task list overflow) taskId=" + + taskInfo.taskId + ", baseIntent=" + taskInfo.baseIntent); + } itr.remove(); return; } @@ -128,6 +152,9 @@ public class TopTaskTracker extends ISplitScreenListener.Stub @Override public void onStagePositionChanged(@StageType int stage, @StagePosition int position) { + if (DEBUG) { + Log.i(TAG, "onStagePositionChanged: stage=" + stage + ", position=" + position); + } if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) { mMainStagePosition.stagePosition = position; } else { @@ -137,6 +164,10 @@ public class TopTaskTracker extends ISplitScreenListener.Stub @Override public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) { + if (DEBUG) { + Log.i(TAG, "onTaskStageChanged: taskId=" + taskId + + ", stage=" + stage + ", visible=" + visible); + } // If a task is not visible anymore or has been moved to undefined, stop tracking it. if (!visible || stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) { if (mMainStagePosition.taskId == taskId) { @@ -156,11 +187,18 @@ public class TopTaskTracker extends ISplitScreenListener.Stub @Override public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { + if (DEBUG) { + Log.i(TAG, "onActivityPinned: packageName=" + packageName + + ", userId=" + userId + ", stackId=" + stackId); + } mPinnedTaskId = taskId; } @Override public void onActivityUnpinned() { + if (DEBUG) { + Log.i(TAG, "onActivityUnpinned"); + } mPinnedTaskId = INVALID_TASK_ID; } @@ -212,6 +250,21 @@ public class TopTaskTracker extends ISplitScreenListener.Stub return new CachedTaskInfo(tasks); } + public void dump(String prefix, PrintWriter writer) { + writer.println(prefix + "TopTaskTracker:"); + + writer.println(prefix + "\tmOrderedTaskList=["); + for (RunningTaskInfo taskInfo : mOrderedTaskList) { + writer.println(prefix + "\t\t(taskId=" + taskInfo.taskId + + "; baseIntent=" + taskInfo.baseIntent + + "; isRunning=" + taskInfo.isRunning + ")"); + } + writer.println(prefix + "\t]"); + writer.println(prefix + "\tmMainStagePosition=" + mMainStagePosition); + writer.println(prefix + "\tmSideStagePosition=" + mSideStagePosition); + writer.println(prefix + "\tmPinnedTaskId=" + mPinnedTaskId); + } + /** * Class to provide information about a task which can be safely cached and do not change * during the lifecycle of the task. diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 4599f180b1..7d460a6d68 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -1467,6 +1467,7 @@ public class TouchInteractionService extends Service { pw.println("\tmConsumer=" + mConsumer.getName()); ActiveGestureLog.INSTANCE.dump("", pw); RecentsModel.INSTANCE.get(this).dump("", pw); + TopTaskTracker.INSTANCE.get(this).dump("", pw); if (mTaskAnimationManager != null) { mTaskAnimationManager.dump("", pw); } diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java index 837d7bc04d..95624b1cb3 100644 --- a/src/com/android/launcher3/util/SplitConfigurationOptions.java +++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java @@ -186,6 +186,12 @@ public final class SplitConfigurationOptions { public int stagePosition = STAGE_POSITION_UNDEFINED; @StageType public int stageType = STAGE_TYPE_UNDEFINED; + + @Override + public String toString() { + return "SplitStageInfo { taskId=" + taskId + + ", stagePosition=" + stagePosition + ", stageType=" + stageType + " }"; + } } public static StatsLogManager.EventEnum getLogEventForPosition(@StagePosition int position) { From 833639d8faaff95cedc055731e3815566c7066b9 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 5 Jun 2024 15:35:39 +0100 Subject: [PATCH 056/143] Fix TaskView.getThumbnailBounds not combining bounds correctly if relativeToDragLayer is true - This was a coding error introduced in ag/27382735 - getThumbnailBounds is supposed to union all individual thumbnailBounds per TaskContainer, rather than overriding bounds over and over per TaskContainer Bug: 339787250 Test: Swipe up to home from split apps Flag: EXEMPT bugfix Change-Id: I7a697620f4b4507df8f1860b4c2f9889e4be006b --- quickstep/src/com/android/quickstep/views/TaskView.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index cae23a17a5..a3a00b4696 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -789,7 +789,10 @@ constructor( taskContainers.forEach { val thumbnailBounds = Rect() if (relativeToDragLayer) { - container.dragLayer.getDescendantRectRelativeToSelf(it.snapshotView, bounds) + container.dragLayer.getDescendantRectRelativeToSelf( + it.snapshotView, + thumbnailBounds + ) } else { thumbnailBounds.set(it.snapshotView) } From 72297b7b81a0a44dc714faf713b70cad47744ca5 Mon Sep 17 00:00:00 2001 From: Himanshu Gupta Date: Wed, 5 Jun 2024 15:40:09 +0100 Subject: [PATCH 057/143] Re-enabling a failing Tapl test for Private Space. The test seemed to be failing due to animation issues (settings cog and Lock text not visible)- b//339179262 Re-enabling the test as those issues are now fixed. Bug: 322882655 Test: TaplPrivateSpaceTest Flag: None TaplTest Change-Id: I4053b9759cd97c721ea576965f57ef309fffaab3 --- .../tests/src/com/android/quickstep/TaplPrivateSpaceTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java index 82905085fe..729452aff1 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java @@ -35,7 +35,6 @@ import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.rule.ScreenRecordRule; import org.junit.After; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -167,7 +166,6 @@ public class TaplPrivateSpaceTest extends AbstractQuickStepTest { @Test @ScreenRecordRule.ScreenRecord // b/334946529 - @Ignore("b/339179262") public void testPrivateSpaceLockingBehaviour() throws IOException { // Scroll to the bottom of All Apps executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader()); From cd4c9d153d1bd599581a01fee518bb08f2b26000 Mon Sep 17 00:00:00 2001 From: Ats Jenk Date: Tue, 4 Jun 2024 11:55:27 -0700 Subject: [PATCH 058/143] Add content description to bubble bar and bubbles Set content description on the bubble bar when it is collapsed. Only allow focus on the bar itself. In collapsed mode, bubbles in the bar can't be focused. Content description for the bar matches what we have in floating mode. We include the text for the first bubble and then how many bubbles are there more. Set content description on bubbles in bubble bar. When bubble bar is expanded, only the bubbles are focusable. Bubble content description matches the floating bubbles content description. Includes the notification title and app name. Bug: 344670947 Flag: com.android.wm.shell.enable_bubble_bar Test: enable talkback, focus on bubble bar when it is collapsed, check that only bubble bar receives focus Test: enable talkback and expand bubble bar, check that only the bubbles receive focus Change-Id: Id931f0360b9ebadd01dd16b05b75546fcc4df803 --- .../taskbar/bubbles/BubbleBarView.java | 47 +++++++++++++++++++ .../launcher3/taskbar/bubbles/BubbleView.java | 11 +++++ .../animation/BubbleBarViewAnimatorTest.kt | 3 +- res/values/strings.xml | 6 +++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index 23e52e6f71..7eeea8431d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -623,6 +623,8 @@ public class BubbleBarView extends FrameLayout { } super.addView(child, index, params); updateWidth(); + updateBubbleAccessibilityStates(); + updateContentDescription(); } // TODO: (b/283309949) animate it @@ -634,6 +636,8 @@ public class BubbleBarView extends FrameLayout { mBubbleBarBackground.showArrow(false); } updateWidth(); + updateBubbleAccessibilityStates(); + updateContentDescription(); } private void updateWidth() { @@ -799,6 +803,7 @@ public class BubbleBarView extends FrameLayout { } } updateChildrenRenderNodeProperties(mBubbleBarLocation); + updateContentDescription(); } } @@ -927,6 +932,7 @@ public class BubbleBarView extends FrameLayout { } else { mWidthAnimator.reverse(); } + updateBubbleAccessibilityStates(); } } @@ -998,6 +1004,47 @@ public class BubbleBarView extends FrameLayout { return mIsAnimatingNewBubble; } + private boolean hasOverview() { + // Overview is always the last bubble + View lastChild = getChildAt(getChildCount() - 1); + if (lastChild instanceof BubbleView bubbleView) { + return bubbleView.getBubble() instanceof BubbleBarOverflow; + } + return false; + } + + private void updateBubbleAccessibilityStates() { + final int childA11y; + if (mIsBarExpanded) { + // Bar is expanded, focus on the bubbles + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + childA11y = View.IMPORTANT_FOR_ACCESSIBILITY_YES; + } else { + // Bar is collapsed, only focus on the bar + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + childA11y = View.IMPORTANT_FOR_ACCESSIBILITY_NO; + } + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).setImportantForAccessibility(childA11y); + // Only allowing focusing on bubbles when bar is expanded. Otherwise, in talkback mode, + // bubbles can be navigates to in collapsed mode. + getChildAt(i).setFocusable(mIsBarExpanded); + } + } + + private void updateContentDescription() { + View firstChild = getChildAt(0); + CharSequence contentDesc = firstChild != null ? firstChild.getContentDescription() : ""; + + // Don't count overflow if it exists + int bubbleCount = getChildCount() - (hasOverview() ? 1 : 0); + if (bubbleCount > 1) { + contentDesc = getResources().getString(R.string.bubble_bar_description_multiple_bubbles, + contentDesc, bubbleCount - 1); + } + setContentDescription(contentDesc); + } + /** Interface for BubbleBarView to communicate with its controller. */ interface Controller { diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java index 2e37dc7695..2f92fbbaba 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java @@ -21,6 +21,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Outline; import android.graphics.Rect; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -187,6 +188,16 @@ public class BubbleView extends ConstraintLayout { mAppIcon.setImageBitmap(bubble.getBadge()); mDotColor = bubble.getDotColor(); mDotRenderer = new DotRenderer(mBubbleSize, bubble.getDotPath(), DEFAULT_PATH_SIZE); + String contentDesc = bubble.getInfo().getTitle(); + if (TextUtils.isEmpty(contentDesc)) { + contentDesc = getResources().getString(R.string.bubble_bar_bubble_fallback_description); + } + String appName = bubble.getInfo().getAppName(); + if (!TextUtils.isEmpty(appName)) { + contentDesc = getResources().getString(R.string.bubble_bar_bubble_description, + contentDesc, appName); + } + setContentDescription(contentDesc); } /** diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt index 49e54fb1f1..cc579abc9e 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt @@ -392,7 +392,8 @@ class BubbleBarViewAnimatorTest { overflowView.setOverflow(BubbleBarOverflow(overflowView), bitmap) bubbleBarView.addView(overflowView) - val bubbleInfo = BubbleInfo("key", 0, null, null, 0, context.packageName, null, false) + val bubbleInfo = + BubbleInfo("key", 0, null, null, 0, context.packageName, null, null, false) bubbleView = inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView bubble = diff --git a/res/values/strings.xml b/res/values/strings.xml index 207d246933..6fe4e6b76b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -500,6 +500,12 @@ Install apps to Private Space + + Bubble Overflow + + %1$s from %2$s + + %1$s and %2$d more From 96396eea951304e9c19e2cba1150dd8f68fdf18a Mon Sep 17 00:00:00 2001 From: Ats Jenk Date: Tue, 4 Jun 2024 16:22:02 -0700 Subject: [PATCH 059/143] Move bubble bar strings Move strings to quickstep as bubble bar is in that folder. Bug: 344670947 Flag: com.android.wm.shell.enable_bubble_bar Test: manual, check talkback on bubble bar and bubbles Change-Id: I2da1f0c8fc6ec13f04b2c75c9eb1a27ec598d564 --- quickstep/res/values/strings.xml | 10 ++++++++++ res/values/strings.xml | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index cf987c3db3..340d25b0f9 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -332,4 +332,14 @@ %1$s and %2$s + + + + Bubble + + Overflow + + %1$s from %2$s + + %1$s and %2$d more diff --git a/res/values/strings.xml b/res/values/strings.xml index 6fe4e6b76b..a9cca6de41 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -498,14 +498,4 @@ Install Install apps to Private Space - - - - Bubble - - Overflow - - %1$s from %2$s - - %1$s and %2$d more From a44f4ac861c86e7477b8288b2a281d2012a2879f Mon Sep 17 00:00:00 2001 From: Sihua Ma Date: Mon, 3 Jun 2024 18:35:39 +0000 Subject: [PATCH 060/143] Push a potential fix for hotseat aggregation This could be caused by landscape layout not receiving inset changes Adding logs for hotseat layout info as well Bug: 335141365 Flag: EXEMPT bugfix Test: N/A Change-Id: I987f8622907a10fac5375ddddac3db2c5eba41c1 --- .../launcher3/BaseDraggingActivity.java | 3 +- src/com/android/launcher3/Hotseat.java | 4 +++ src/com/android/launcher3/ModelCallbacks.kt | 28 +++++++++++++------ .../launcher3/WorkspaceLayoutManager.java | 3 ++ 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index cf93a79c54..8585b66554 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -147,7 +147,8 @@ public abstract class BaseDraggingActivity extends BaseActivity @Override public void onDisplayInfoChanged(Context context, Info info, int flags) { - if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.updateIsSeascape(this)) { + if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.isVerticalBarLayout()) { + mDeviceProfile.updateIsSeascape(this); reapplyUi(); } } diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 37737d81a3..854645418a 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -82,6 +82,10 @@ public class Hotseat extends CellLayout implements Insettable { return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0; } + boolean isHasVerticalHotseat() { + return mHasVerticalHotseat; + } + public void resetLayout(boolean hasVerticalHotseat) { ActivityContext activityContext = ActivityContext.lookupContext(getContext()); boolean bubbleBarEnabled = activityContext.isBubbleBarEnabled(); diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt index 7d6d154bde..13062b6b1b 100644 --- a/src/com/android/launcher3/ModelCallbacks.kt +++ b/src/com/android/launcher3/ModelCallbacks.kt @@ -3,6 +3,7 @@ package com.android.launcher3 import android.annotation.TargetApi import android.os.Build import android.os.Trace +import android.util.Log import androidx.annotation.UiThread import com.android.launcher3.Flags.enableSmartspaceRemovalToggle import com.android.launcher3.LauncherConstants.TraceEvents @@ -29,6 +30,8 @@ import com.android.launcher3.widget.PendingAddWidgetInfo import com.android.launcher3.widget.model.WidgetsListBaseEntry import java.util.function.Predicate +private const val TAG = "ModelCallbacks" + class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { var synchronouslyBoundPages = LIntSet() @@ -66,6 +69,13 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { launcher.workspace.removeAllWorkspaceScreens() // Avoid clearing the widget update listeners for staying up-to-date with widget info launcher.appWidgetHolder.clearWidgetViews() + // TODO(b/335141365): Remove this log after the bug is fixed. + Log.d( + TAG, + "startBinding: " + + "hotseat layout was vertical: ${launcher.hotseat?.isHasVerticalHotseat}" + + " and is setting to ${launcher.deviceProfile.isVerticalBarLayout}" + ) launcher.hotseat?.resetLayout(launcher.deviceProfile.isVerticalBarLayout) TraceHelper.INSTANCE.endSection() } @@ -142,7 +152,10 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { launcher.viewCache.setCacheSize(R.layout.folder_page, 2) TraceHelper.INSTANCE.endSection() launcher.workspace.removeExtraEmptyScreen(/* stripEmptyScreens= */ true) - launcher.workspace.pageIndicator.setPauseScroll(/*pause=*/ false, deviceProfile.isTwoPanels) + launcher.workspace.pageIndicator.setPauseScroll( + /*pause=*/ false, + deviceProfile.isTwoPanels + ) } /** @@ -290,8 +303,7 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { val widgetsListBaseEntry: WidgetsListBaseEntry = launcher.popupDataProvider.allWidgets.firstOrNull { item: WidgetsListBaseEntry -> item.mPkgItem.packageName == BuildConfig.APPLICATION_ID - } - ?: return + } ?: return val info = PendingAddWidgetInfo( @@ -315,16 +327,14 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { ) val firstScreenPosition = 0 if ( - (isFirstPagePinnedItemEnabled && - !SHOULD_SHOW_FIRST_PAGE_WIDGET) && + (isFirstPagePinnedItemEnabled && !SHOULD_SHOW_FIRST_PAGE_WIDGET) && orderedScreenIds.indexOf(FIRST_SCREEN_ID) != firstScreenPosition ) { orderedScreenIds.removeValue(FIRST_SCREEN_ID) orderedScreenIds.add(firstScreenPosition, FIRST_SCREEN_ID) } else if ( - (!isFirstPagePinnedItemEnabled || - SHOULD_SHOW_FIRST_PAGE_WIDGET) - && orderedScreenIds.isEmpty + (!isFirstPagePinnedItemEnabled || SHOULD_SHOW_FIRST_PAGE_WIDGET) && + orderedScreenIds.isEmpty ) { // If there are no screens, we need to have an empty screen launcher.workspace.addExtraEmptyScreens() @@ -380,7 +390,7 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { } orderedScreenIds .filterNot { screenId -> - isFirstPagePinnedItemEnabled && + isFirstPagePinnedItemEnabled && !SHOULD_SHOW_FIRST_PAGE_WIDGET && screenId == WorkspaceLayoutManager.FIRST_SCREEN_ID } diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java index 4768773813..f11a88fa10 100644 --- a/src/com/android/launcher3/WorkspaceLayoutManager.java +++ b/src/com/android/launcher3/WorkspaceLayoutManager.java @@ -58,6 +58,9 @@ public interface WorkspaceLayoutManager { int screenId = presenterPos.screenId; x = getHotseat().getCellXFromOrder(screenId); y = getHotseat().getCellYFromOrder(screenId); + // TODO(b/335141365): Remove this log after the bug is fixed. + Log.d(TAG, "addInScreenFromBind: hotseat inflation with x = " + x + + " and y = " + y); } addInScreen(child, info.container, presenterPos.screenId, x, y, info.spanX, info.spanY); } From 4d8ad445c06ce85ef95f2b3f9bfb5d4d31c1ddd5 Mon Sep 17 00:00:00 2001 From: mpodolian Date: Tue, 4 Jun 2024 22:36:35 +0100 Subject: [PATCH 061/143] Remove scrim view alpha when bubble manage menu is shown. Updated logic for taskbar scrim view alpha calculation, setting it to 0 when bubble manage menu is shown. Fixes: 337169457 Flag: NONE Test: Visual. For gesture navigation: 1) On foldable phone while device is being folded expand any bubble, click mange button, then unfold. Observe no scrim view is visible. 2) Enable persistent taskbar, pull down the notification shade then swipe it back up while bubbles are open. 3) Enable persistent taskbar, pull down the notification shade then swipe it back up while bubbles and mange menu is open. 4) Enable persistent taskbar. Fold device. Open bubble and click manage button. Unfold device. Observe no scrim view is visible. For 3 button navigation 1) Unfold the device, press the home key, pull down the notification shade then swipe it back up while bubbles are open. 2) Unfold the device, press the home key, pull down the notification shade then swipe it back up while bubbles and mange menu is open. 3) Fold device, open bubble and click manage button. Unfold device. Observe no scrim view is visible. Change-Id: Ic011ae9bd11801a479062cc51c60377823a926fb --- .../taskbar/TaskbarScrimViewController.java | 18 ++++++++++++------ .../launcher3/util/DisplayController.java | 4 +++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java index 92d9b23cb6..48d2bc2ff7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java @@ -103,14 +103,20 @@ public class TaskbarScrimViewController implements TaskbarControllers.LoggableTa } private float getScrimAlpha() { + final boolean isPersistentTaskBarVisible = + mTaskbarVisible && !DisplayController.isTransientTaskbar(mScrimView.getContext()); final boolean manageMenuExpanded = (mSysUiStateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0; - return manageMenuExpanded - // When manage menu shows there's the first scrim and second scrim so figure out - // what the total transparency would be. - ? (BUBBLE_EXPANDED_SCRIM_ALPHA + (BUBBLE_EXPANDED_SCRIM_ALPHA - * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA))) - : shouldShowScrim() ? BUBBLE_EXPANDED_SCRIM_ALPHA : 0; + if (isPersistentTaskBarVisible && manageMenuExpanded) { + // When manage menu shows for persistent task bar there's the first scrim and second + // scrim so figure out what the total transparency would be. + return BUBBLE_EXPANDED_SCRIM_ALPHA + + (BUBBLE_EXPANDED_SCRIM_ALPHA * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA)); + } else if (shouldShowScrim()) { + return BUBBLE_EXPANDED_SCRIM_ALPHA; + } else { + return 0; + } } private void showScrim(boolean showScrim, float alpha, boolean skipAnim) { diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index 92fc38ff71..fa01986535 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -174,7 +174,9 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { } /** - * Returns whether taskbar is transient. + * Returns whether taskbar is transient or persistent. + * + * @return {@code true} if transient, {@code false} if persistent. */ public static boolean isTransientTaskbar(Context context) { return INSTANCE.get(context).getInfo().isTransientTaskbar(); From 762b3b4685225cbb2b106ac2c82ced50e19404cc Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 5 Jun 2024 17:37:02 +0000 Subject: [PATCH 062/143] Always report mandatory insets for button nav Fixes: 340134342 Fixes: 343817842 Test: atest android.systemui.cts.WindowInsetsBehaviorTests Test: Verify mandatory insets vs window bounds in various orientations when folded/unfolded Change-Id: I18d4f5d212d16c62d15d84b4842b3d20c0d8c5ae --- .../com/android/launcher3/taskbar/TaskbarInsetsController.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index e1ddb6a951..0b60e455b2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -236,7 +236,8 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, endRotation) } else if (provider.type == mandatorySystemGestures()) { if (context.isThreeButtonNav) { - provider.insetsSize = Insets.of(0, 0, 0, 0) + provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, + endRotation) } else { val gestureHeight = ResourceUtils.getNavbarSize( From 50fa2e404f9c22a5032a62de81ad5017b4e05324 Mon Sep 17 00:00:00 2001 From: Shamali Patwa Date: Thu, 6 Jun 2024 14:06:17 +0000 Subject: [PATCH 063/143] Fix the flaky screenshot test The flake happened to be due to rebinding triggered on attachToWindow that reset the icon cache with placeholder icon Based on what I see, instead of calling refresh and bind, just triggerring onWidgetsBound should be okay - assuming it was trying to bind view for case when theme or display size was changed while picker was open. Bug: 337916664 Change-Id: Ic6f3ff9188e4c5eda141a948ffa0c2c7c685162e Test: Screenshot test Flag: EXEMPT bugfix for test --- src/com/android/launcher3/widget/picker/WidgetsFullSheet.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java index 3be6faa358..9929892e28 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java @@ -330,8 +330,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - LauncherAppState.getInstance(mActivityContext).getModel() - .refreshAndBindWidgetsAndShortcuts(null); + onWidgetsBound(); } @Override From 87e579ea2d866ee5d87a172d8b4931a7aaf26947 Mon Sep 17 00:00:00 2001 From: Liran Binyamin Date: Thu, 6 Jun 2024 16:35:22 -0400 Subject: [PATCH 064/143] Fix bubble visibility issue when collapsed When the bubble bar collapses, explicitly set the alpha to 1 for bubbles that should not be hidden. Flag: com.android.wm.shell.enable_bubble_bar Fixes: 345283193 Test: manual - create 3 bubbles in the bar - tap to expand - select the last bubble - tap it again to collapse - observe it is visible Change-Id: I1aed310b66433b88b08ccaf760fc8e82923b1b64 --- .../com/android/launcher3/taskbar/bubbles/BubbleBarView.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index 23e52e6f71..dbab3f05e4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -715,6 +715,8 @@ public class BubbleBarView extends FrameLayout { } else if (i == MAX_VISIBLE_BUBBLES_COLLAPSED - 1 && bubbleCount == MAX_VISIBLE_BUBBLES_COLLAPSED) { bv.setAlpha(0); + } else { + bv.setAlpha(1); } } } From 9f27418e26eacbd75932540ecb72aed6ca421e7a Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 6 Jun 2024 14:20:04 -0700 Subject: [PATCH 065/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ia31223d4855e3e922380932ee02414638c589526 --- quickstep/res/values-af/strings.xml | 8 ++++++++ quickstep/res/values-am/strings.xml | 8 ++++++++ quickstep/res/values-ar/strings.xml | 8 ++++++++ quickstep/res/values-as/strings.xml | 8 ++++++++ quickstep/res/values-az/strings.xml | 8 ++++++++ quickstep/res/values-b+sr+Latn/strings.xml | 8 ++++++++ quickstep/res/values-be/strings.xml | 8 ++++++++ quickstep/res/values-bg/strings.xml | 8 ++++++++ quickstep/res/values-bn/strings.xml | 8 ++++++++ quickstep/res/values-bs/strings.xml | 8 ++++++++ quickstep/res/values-ca/strings.xml | 8 ++++++++ quickstep/res/values-cs/strings.xml | 8 ++++++++ quickstep/res/values-da/strings.xml | 8 ++++++++ quickstep/res/values-de/strings.xml | 8 ++++++++ quickstep/res/values-el/strings.xml | 8 ++++++++ quickstep/res/values-en-rAU/strings.xml | 8 ++++++++ quickstep/res/values-en-rCA/strings.xml | 8 ++++++++ quickstep/res/values-en-rGB/strings.xml | 8 ++++++++ quickstep/res/values-en-rIN/strings.xml | 8 ++++++++ quickstep/res/values-en-rXC/strings.xml | 8 ++++++++ quickstep/res/values-es-rUS/strings.xml | 8 ++++++++ quickstep/res/values-es/strings.xml | 8 ++++++++ quickstep/res/values-et/strings.xml | 10 +++++++++- quickstep/res/values-eu/strings.xml | 8 ++++++++ quickstep/res/values-fa/strings.xml | 8 ++++++++ quickstep/res/values-fi/strings.xml | 8 ++++++++ quickstep/res/values-fr-rCA/strings.xml | 8 ++++++++ quickstep/res/values-fr/strings.xml | 8 ++++++++ quickstep/res/values-gl/strings.xml | 8 ++++++++ quickstep/res/values-gu/strings.xml | 8 ++++++++ quickstep/res/values-hi/strings.xml | 8 ++++++++ quickstep/res/values-hr/strings.xml | 8 ++++++++ quickstep/res/values-hu/strings.xml | 8 ++++++++ quickstep/res/values-hy/strings.xml | 8 ++++++++ quickstep/res/values-in/strings.xml | 8 ++++++++ quickstep/res/values-is/strings.xml | 8 ++++++++ quickstep/res/values-it/strings.xml | 8 ++++++++ quickstep/res/values-iw/strings.xml | 8 ++++++++ quickstep/res/values-ja/strings.xml | 8 ++++++++ quickstep/res/values-ka/strings.xml | 8 ++++++++ quickstep/res/values-kk/strings.xml | 8 ++++++++ quickstep/res/values-km/strings.xml | 8 ++++++++ quickstep/res/values-kn/strings.xml | 8 ++++++++ quickstep/res/values-ko/strings.xml | 8 ++++++++ quickstep/res/values-ky/strings.xml | 8 ++++++++ quickstep/res/values-lo/strings.xml | 8 ++++++++ quickstep/res/values-lt/strings.xml | 8 ++++++++ quickstep/res/values-lv/strings.xml | 8 ++++++++ quickstep/res/values-mk/strings.xml | 8 ++++++++ quickstep/res/values-ml/strings.xml | 8 ++++++++ quickstep/res/values-mn/strings.xml | 8 ++++++++ quickstep/res/values-mr/strings.xml | 8 ++++++++ quickstep/res/values-ms/strings.xml | 8 ++++++++ quickstep/res/values-my/strings.xml | 8 ++++++++ quickstep/res/values-nb/strings.xml | 8 ++++++++ quickstep/res/values-ne/strings.xml | 8 ++++++++ quickstep/res/values-nl/strings.xml | 8 ++++++++ quickstep/res/values-or/strings.xml | 8 ++++++++ quickstep/res/values-pa/strings.xml | 8 ++++++++ quickstep/res/values-pl/strings.xml | 8 ++++++++ quickstep/res/values-pt-rPT/strings.xml | 8 ++++++++ quickstep/res/values-pt/strings.xml | 8 ++++++++ quickstep/res/values-ro/strings.xml | 8 ++++++++ quickstep/res/values-ru/strings.xml | 8 ++++++++ quickstep/res/values-si/strings.xml | 8 ++++++++ quickstep/res/values-sk/strings.xml | 8 ++++++++ quickstep/res/values-sl/strings.xml | 8 ++++++++ quickstep/res/values-sq/strings.xml | 8 ++++++++ quickstep/res/values-sr/strings.xml | 8 ++++++++ quickstep/res/values-sv/strings.xml | 8 ++++++++ quickstep/res/values-sw/strings.xml | 8 ++++++++ quickstep/res/values-ta/strings.xml | 8 ++++++++ quickstep/res/values-te/strings.xml | 8 ++++++++ quickstep/res/values-th/strings.xml | 8 ++++++++ quickstep/res/values-tl/strings.xml | 8 ++++++++ quickstep/res/values-tr/strings.xml | 8 ++++++++ quickstep/res/values-uk/strings.xml | 8 ++++++++ quickstep/res/values-ur/strings.xml | 8 ++++++++ quickstep/res/values-uz/strings.xml | 8 ++++++++ quickstep/res/values-vi/strings.xml | 8 ++++++++ quickstep/res/values-zh-rCN/strings.xml | 8 ++++++++ quickstep/res/values-zh-rHK/strings.xml | 8 ++++++++ quickstep/res/values-zh-rTW/strings.xml | 8 ++++++++ quickstep/res/values-zu/strings.xml | 8 ++++++++ 84 files changed, 673 insertions(+), 1 deletion(-) diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml index 0b03e02122..f7bf7198e1 100644 --- a/quickstep/res/values-af/strings.xml +++ b/quickstep/res/values-af/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}" "{count,plural, =1{Wys # rekenaarapp.}other{Wys # rekenaarapps.}}" "%1$s en %2$s" + + + + + + + + diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml index c8fd27668f..1700823424 100644 --- a/quickstep/res/values-am/strings.xml +++ b/quickstep/res/values-am/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}" "{count,plural, =1{# የዴስክቶፕ መተግበሪያ አሳይ።}one{# የዴስክቶፕ መተግበሪያ አሳይ።}other{# የዴስክቶፕ መተግበሪያዎች አሳይ።}}" "%1$s እና %2$s" + + + + + + + + diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index ca0e1dda9b..38e9f701b2 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}" "{count,plural, =1{عرض تطبيق واحد متوافق مع الكمبيوتر المكتبي}zero{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}two{عرض تطبيقَين متوافقين مع الكمبيوتر المكتبي}few{عرض # تطبيقات متوافقة مع الكمبيوتر المكتبي}many{عرض # تطبيقًا متوافقًا مع الكمبيوتر المكتبي}other{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}}" "\"%1$s\" و\"%2$s\"" + + + + + + + + diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml index 7cd769645c..5ba91634ae 100644 --- a/quickstep/res/values-as/strings.xml +++ b/quickstep/res/values-as/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{আৰু # টা এপ্‌ দেখুৱাওক।}one{আৰু # টা এপ্‌ দেখুৱাওক।}other{আৰু # টা এপ্‌ দেখুৱাওক।}}" "{count,plural, =1{# টা ডেস্কটপ এপ্ দেখুৱাওক।}one{# টা ডেস্কটপ এপ্ দেখুৱাওক।}other{# টা ডেস্কটপ এপ্ দেখুৱাওক।}}" "%1$s আৰু %2$s" + + + + + + + + diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml index f5840abbc9..ab753679b6 100644 --- a/quickstep/res/values-az/strings.xml +++ b/quickstep/res/values-az/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}" "{count,plural, =1{# masaüstü tətbiqini göstərin.}other{# masaüstü tətbiqini göstərin.}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml index 276a8b9549..d23ba50e0b 100644 --- a/quickstep/res/values-b+sr+Latn/strings.xml +++ b/quickstep/res/values-b+sr+Latn/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}" "{count,plural, =1{Prikaži # aplikaciju za računare.}one{Prikaži # aplikaciju za računare.}few{Prikaži # aplikacije za računare.}other{Prikaži # aplikacija za računare.}}" "%1$s i %2$s" + + + + + + + + diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml index 0785e0f487..2829fd9962 100644 --- a/quickstep/res/values-be/strings.xml +++ b/quickstep/res/values-be/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}" "{count,plural, =1{Паказаць # праграму для ПК.}one{Паказаць # праграму для ПК.}few{Паказаць # праграмы для ПК.}many{Паказаць # праграм для ПК.}other{Паказаць # праграмы для ПК.}}" "%1$s і %2$s" + + + + + + + + diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index c26bc6fd93..bb7d7be7c5 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}" "{count,plural, =1{Показване на # настолно приложение.}other{Показване на # настолни приложения.}}" "%1$s и %2$s" + + + + + + + + diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml index f7f666bb9e..ebde96d0ab 100644 --- a/quickstep/res/values-bn/strings.xml +++ b/quickstep/res/values-bn/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}" "{count,plural, =1{#টি ডেস্কটপ অ্যাপ দেখুন।}one{#টি ডেস্কটপ অ্যাপ দেখুন।}other{#টি ডেস্কটপ অ্যাপ দেখুন।}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml index 11671452b2..89cdc285e0 100644 --- a/quickstep/res/values-bs/strings.xml +++ b/quickstep/res/values-bs/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}" "{count,plural, =1{Prikaži # aplikaciju za računar.}one{Prikaži # aplikaciju za računar.}few{Prikaži # aplikacije za računar.}other{Prikaži # aplikacija za računar.}}" "%1$s i %2$s" + + + + + + + + diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index ba8e3c160e..f1768aa47f 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}" "{count,plural, =1{Mostra # aplicació per a ordinadors.}other{Mostra # aplicacions per a ordinadors.}}" "%1$s i %2$s" + + + + + + + + diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index 7f1cd94f9c..6c523ca337 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}" "{count,plural, =1{Zobrazit # aplikaci pro počítač.}few{Zobrazit # aplikace pro počítač.}many{Zobrazit # aplikace pro počítač.}other{Zobrazit # aplikací pro počítač.}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml index 1daf365c49..a8d361212b 100644 --- a/quickstep/res/values-da/strings.xml +++ b/quickstep/res/values-da/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}" "{count,plural, =1{Vis # computerprogram.}one{Vis # computerprogram.}other{Vis # computerprogrammer.}}" "%1$s og %2$s" + + + + + + + + diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index b089976936..bc15ca530a 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# weitere App anzeigen}other{# weitere Apps anzeigen}}" "{count,plural, =1{# Desktop-App anzeigen.}other{# Desktop-Apps anzeigen.}}" "%1$s und %2$s" + + + + + + + + diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml index 66ca90ecbe..c317aa470c 100644 --- a/quickstep/res/values-el/strings.xml +++ b/quickstep/res/values-el/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}" "{count,plural, =1{Εμφάνιση # εφαρμογής υπολογιστή.}other{Εμφάνιση # εφαρμογών υπολογιστή.}}" "%1$s και %2$s" + + + + + + + + diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml index fe5b479bcd..519146b17b 100644 --- a/quickstep/res/values-en-rAU/strings.xml +++ b/quickstep/res/values-en-rAU/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" + + + + + + + + diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml index 3bd2bdd85f..4205e49c6c 100644 --- a/quickstep/res/values-en-rCA/strings.xml +++ b/quickstep/res/values-en-rCA/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" + + + + + + + + diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml index fe5b479bcd..519146b17b 100644 --- a/quickstep/res/values-en-rGB/strings.xml +++ b/quickstep/res/values-en-rGB/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" + + + + + + + + diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml index fe5b479bcd..519146b17b 100644 --- a/quickstep/res/values-en-rIN/strings.xml +++ b/quickstep/res/values-en-rIN/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" + + + + + + + + diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml index 52efe9d08b..44afeddbdd 100644 --- a/quickstep/res/values-en-rXC/strings.xml +++ b/quickstep/res/values-en-rXC/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more apps.‎‏‎‎‏‎}}" "{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎Show # desktop app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎Show # desktop apps.‎‏‎‎‏‎}}" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + + + + + + + + diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index 095b06e2d4..4930c0b6be 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}" "{count,plural, =1{Mostrar # app para computadoras.}other{Mostrar # apps para computadoras.}}" "%1$s y %2$s" + + + + + + + + diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index dbc7caaa88..4b45f5ef07 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}" "{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicaciones para ordenadores.}}" "%1$s y %2$s" + + + + + + + + diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml index c53f80c64f..d6b9e7848e 100644 --- a/quickstep/res/values-et/strings.xml +++ b/quickstep/res/values-et/strings.xml @@ -73,7 +73,7 @@ "Pühkige kindlasti ekraani alumisest servast üles." "Hoidke sõrme aknal pisut kauem, enne kui vabastate" "Pühkige kindlasti otse üles, seejärel peatuge" - "Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage seaded." + "Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage Seaded." "Tegite rakenduste vahel vahetamise liigutuse" "Pühkige rakenduste vahetamiseks" "Rakenduste vahel vahetamiseks pühkige ekraanikuva alaosast üles, hoidke ja seejärel vabastage." @@ -140,4 +140,12 @@ "{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}" "{count,plural, =1{Kuva # töölauarakendus.}other{Kuva # töölauarakendust.}}" "%1$s ja %2$s" + + + + + + + + diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml index ecdacd2465..bcecfeac25 100644 --- a/quickstep/res/values-eu/strings.xml +++ b/quickstep/res/values-eu/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}" "{count,plural, =1{Erakutsi ordenagailuetarako # aplikazio.}other{Erakutsi ordenagailuetarako # aplikazio.}}" "%1$s eta %2$s" + + + + + + + + diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml index 0dad8016aa..a68d77c856 100644 --- a/quickstep/res/values-fa/strings.xml +++ b/quickstep/res/values-fa/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}" "{count,plural, =1{نمایش # برنامه رایانه.}one{نمایش # برنامه رایانه.}other{نمایش # برنامه رایانه.}}" "%1$s و %2$s" + + + + + + + + diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml index 8624fe7b3b..bb0516ccd3 100644 --- a/quickstep/res/values-fi/strings.xml +++ b/quickstep/res/values-fi/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}" "{count,plural, =1{Näytä # työpöytäsovellus.}other{Näytä # työpöytäsovellusta.}}" "%1$s ja %2$s" + + + + + + + + diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index 737380057f..dd36f2e5d3 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}" "{count,plural, =1{Afficher # appli de bureau.}one{Afficher # appli de bureau.}other{Afficher # applis de bureau.}}" "%1$s et %2$s" + + + + + + + + diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml index f19a435e97..de335bfd57 100644 --- a/quickstep/res/values-fr/strings.xml +++ b/quickstep/res/values-fr/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Afficher # autre appli}one{Afficher # autre appli}other{Afficher # autre applis}}" "{count,plural, =1{Afficher # application de bureau.}one{Afficher # application de bureau.}other{Afficher # applications de bureau.}}" "%1$s et %2$s" + + + + + + + + diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml index 0afb2883ba..b116332d11 100644 --- a/quickstep/res/values-gl/strings.xml +++ b/quickstep/res/values-gl/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}" "{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicacións para ordenadores.}}" "%1$s e %2$s" + + + + + + + + diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml index fd5dca6ca2..efba149909 100644 --- a/quickstep/res/values-gu/strings.xml +++ b/quickstep/res/values-gu/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}" "{count,plural, =1{# ડેસ્કટૉપ ઍપ બતાવો.}one{# ડેસ્કટૉપ ઍપ બતાવો.}other{# ડેસ્કટૉપ ઍપ બતાવો.}}" "%1$s અને %2$s" + + + + + + + + diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 246bdc71ef..205be273cf 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}" "{count,plural, =1{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}one{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}other{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}}" "%1$s और %2$s" + + + + + + + + diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index 0069edabbf..d189268b53 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Prikaži još # aplikaciju}one{Prikaži još # aplikaciju}few{Prikaži još # aplikacije}other{Prikaži još # aplikacija}}" "{count,plural, =1{Prikaži # računalnu aplikaciju.}one{Prikaži # računalnu aplikaciju.}few{Prikaži # računalne aplikacije.}other{Prikaži # računalnih aplikacija.}}" "%1$s i %2$s" + + + + + + + + diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml index 162337e388..975966e1de 100644 --- a/quickstep/res/values-hu/strings.xml +++ b/quickstep/res/values-hu/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}" "{count,plural, =1{# asztali alkalmazás megjelenítése.}other{# asztali alkalmazás megjelenítése.}}" "%1$s és %2$s" + + + + + + + + diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml index 8919191c81..7e562583f9 100644 --- a/quickstep/res/values-hy/strings.xml +++ b/quickstep/res/values-hy/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}" "{count,plural, =1{Ցույց տալ # համակարգչային հավելված։}one{Ցույց տալ # համակարգչային հավելված։}other{Ցույց տալ # համակարգչային հավելված։}}" "%1$s և %2$s" + + + + + + + + diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml index ea62b4dd17..d0a7a91494 100644 --- a/quickstep/res/values-in/strings.xml +++ b/quickstep/res/values-in/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Tampilkan # aplikasi lainnya.}other{Tampilkan # aplikasi lainnya.}}" "{count,plural, =1{Tampilkan # aplikasi desktop.}other{Tampilkan # aplikasi desktop.}}" "%1$s dan %2$s" + + + + + + + + diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index 3e204ce0a7..34e5f26e42 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}" "{count,plural, =1{Sýna # skjáborðsforrit.}one{Sýna # skjáborðsforrit.}other{Sýna # skjáborðsforrit.}}" "%1$s og %2$s" + + + + + + + + diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index f295b0730f..a5d11f856c 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}" "{count,plural, =1{Mostra # app desktop.}other{Mostra # app desktop.}}" "%1$s e %2$s" + + + + + + + + diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml index 037deec6d9..30c53d5bdd 100644 --- a/quickstep/res/values-iw/strings.xml +++ b/quickstep/res/values-iw/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}" "{count,plural, =1{הצגת אפליקציה אחת (#) למחשב.}one{הצגת # אפליקציות למחשב.}two{הצגת # אפליקציות למחשב.}other{הצגת # אפליקציות למחשב.}}" "%1$s ו-%2$s" + + + + + + + + diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml index ef335f2a16..ead3c19208 100644 --- a/quickstep/res/values-ja/strings.xml +++ b/quickstep/res/values-ja/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}" "{count,plural, =1{# 個のデスクトップ アプリが表示されます。}other{# 個のデスクトップ アプリが表示されます。}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml index 6da246ab9a..bcc28b489c 100644 --- a/quickstep/res/values-ka/strings.xml +++ b/quickstep/res/values-ka/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}" "{count,plural, =1{# დესკტოპის აპის ჩვენება.}other{# დესკტოპის აპის ჩვენება.}}" "%1$s და %2$s" + + + + + + + + diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index 20a1d5945e..0002024413 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}" "{count,plural, =1{Компьютерге арналған # қолданбаны көрсету}other{Компьютерге арналған # қолданбаны көрсету}}" "%1$s және %2$s" + + + + + + + + diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index 6d5e6f1492..8c38c48777 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញ​កម្មវិធី # ទៀត។}}" "{count,plural, =1{បង្ហាញកម្មវិធី​កុំព្យូទ័រ #។}other{បង្ហាញកម្មវិធី​កុំព្យូទ័រ #។}}" "%1$s និង %2$s" + + + + + + + + diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml index 10ab9224bf..1231157c2e 100644 --- a/quickstep/res/values-kn/strings.xml +++ b/quickstep/res/values-kn/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}" "{count,plural, =1{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್ ತೋರಿಸಿ.}one{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}" "%1$s ಮತ್ತು %2$s" + + + + + + + + diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml index 24934f9fef..e0fc21f0c3 100644 --- a/quickstep/res/values-ko/strings.xml +++ b/quickstep/res/values-ko/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}" "{count,plural, =1{데스크톱 앱 #개를 표시합니다.}other{데스크톱 앱 #개를 표시합니다.}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index 525a248499..fbb1c42ff6 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}" "{count,plural, =1{# иш такта колдонмосун көрсөтүү.}other{# иш такта колдонмосун көрсөтүү.}}" "%1$s жана %2$s" + + + + + + + + diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml index b5a7ebbf72..bb363300ae 100644 --- a/quickstep/res/values-lo/strings.xml +++ b/quickstep/res/values-lo/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}" "{count,plural, =1{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}other{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}}" "%1$s ແລະ %2$s" + + + + + + + + diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml index 4817e25adb..b5dceb6415 100644 --- a/quickstep/res/values-lt/strings.xml +++ b/quickstep/res/values-lt/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}" "{count,plural, =1{Rodyti # darbalaukio programą.}one{Rodyti # darbalaukio programą.}few{Rodyti # darbalaukio programas.}many{Rodyti # darbalaukio programos.}other{Rodyti # darbalaukio programų.}}" "„%1$s“ ir „%2$s“" + + + + + + + + diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml index aa80b7e6ba..2b6208a629 100644 --- a/quickstep/res/values-lv/strings.xml +++ b/quickstep/res/values-lv/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}" "{count,plural, =1{Rādīt # datora lietotni.}zero{Rādīt # datora lietotnes.}one{Rādīt # datora lietotni.}other{Rādīt # datora lietotnes.}}" "“%1$s” un “%2$s”" + + + + + + + + diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml index 039ee9f0fb..6b8c592ff8 100644 --- a/quickstep/res/values-mk/strings.xml +++ b/quickstep/res/values-mk/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}" "{count,plural, =1{Прикажи # апликација за компјутер.}one{Прикажи # апликација за компјутер.}other{Прикажи # апликации за компјутер.}}" "%1$s и %2$s" + + + + + + + + diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml index 8fbc8f7100..d401c20aaa 100644 --- a/quickstep/res/values-ml/strings.xml +++ b/quickstep/res/values-ml/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}" "{count,plural, =1{# ഡെസ്‌ക്ടോപ്പ് ആപ്പ് കാണിക്കുക.}other{# ഡെസ്‌ക്ടോപ്പ് ആപ്പുകൾ കാണിക്കുക.}}" "%1$s, %2$s" + + + + + + + + diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml index d5e41057e3..4491c37531 100644 --- a/quickstep/res/values-mn/strings.xml +++ b/quickstep/res/values-mn/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}" "{count,plural, =1{Компьютерын # аппыг харуулна уу.}other{Компьютерын # аппыг харуулна уу.}}" "%1$s болон %2$s" + + + + + + + + diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index cbce562153..3938fd4dc7 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{आणखी # अ‍ॅप दाखवा.}other{आणखी # अ‍ॅप्स दाखवा.}}" "{count,plural, =1{# डेस्‍कटॉप अ‍ॅप दाखवा.}other{# डेस्‍कटॉप अ‍ॅप्स दाखवा.}}" "%1$s आणि %2$s" + + + + + + + + diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml index cc1ecdd7c1..0db53d6579 100644 --- a/quickstep/res/values-ms/strings.xml +++ b/quickstep/res/values-ms/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}" "{count,plural, =1{Tunjukkan # apl desktop.}other{Tunjukkan # apl desktop.}}" "%1$s dan %2$s" + + + + + + + + diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index 0b3a708e38..4ac838a794 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}" "{count,plural, =1{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}other{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}}" "%1$s နှင့် %2$s" + + + + + + + + diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index 655ffecc02..46bf14b5b5 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Vis # app til.}other{Vis # apper til.}}" "{count,plural, =1{Vis # datamaskinprogram.}other{Vis # datamaskinprogrammer.}}" "%1$s og %2$s" + + + + + + + + diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index 3554aa5c10..07437caf19 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{थप # एप देखाउनुहोस्।}other{थप # वटा एप देखाउनुहोस्।}}" "{count,plural, =1{# डेस्कटप एप देखाउनुहोस्।}other{# वटा डेस्कटप एप देखाउनुहोस्।}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml index c5cebdb71a..3dedd7b040 100644 --- a/quickstep/res/values-nl/strings.xml +++ b/quickstep/res/values-nl/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}" "{count,plural, =1{# desktop-app tonen.}other{# desktop-apps tonen.}}" "%1$s en %2$s" + + + + + + + + diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml index 765935e408..67a5b139d4 100644 --- a/quickstep/res/values-or/strings.xml +++ b/quickstep/res/values-or/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}" "{count,plural, =1{# ଡେସ୍କଟପ ଆପ ଦେଖାନ୍ତୁ।}other{# ଡେସ୍କଟପ ଆପ୍ସ ଦେଖାନ୍ତୁ।}}" "%1$s ଏବଂ %2$s" + + + + + + + + diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml index 769608b0ca..78f1c7951f 100644 --- a/quickstep/res/values-pa/strings.xml +++ b/quickstep/res/values-pa/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}" "{count,plural, =1{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}one{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}other{# ਡੈਸਕਟਾਪ ਐਪਾਂ ਦਿਖਾਓ।}}" "%1$s ਅਤੇ %2$s" + + + + + + + + diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml index 752764fbdc..41ac736ce6 100644 --- a/quickstep/res/values-pl/strings.xml +++ b/quickstep/res/values-pl/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}" "{count,plural, =1{Pokaż # aplikację komputerową.}few{Pokaż # aplikacje komputerowe.}many{Pokaż # aplikacji komputerowych.}other{Pokaż # aplikacji komputerowej.}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index a692e69b3e..f674d687f3 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}" "{count,plural, =1{Mostrar # app para computador.}other{Mostrar # apps para computador.}}" "%1$s e %2$s" + + + + + + + + diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index dd3c037829..4f3d75ade1 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}" "{count,plural, =1{Mostrar # app para computador.}one{Mostrar # app para computador.}other{Mostrar # apps para computador.}}" "%1$s e %2$s" + + + + + + + + diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml index 7efeda27fb..dee1ac613e 100644 --- a/quickstep/res/values-ro/strings.xml +++ b/quickstep/res/values-ro/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}" "{count,plural, =1{Afișează # aplicație pentru computer.}few{Afișează # aplicații pentru computer.}other{Afișează # de aplicații pentru computer.}}" "%1$s și %2$s" + + + + + + + + diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml index e8d1ddb441..a78561a687 100644 --- a/quickstep/res/values-ru/strings.xml +++ b/quickstep/res/values-ru/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}" "{count,plural, =1{Показать # компьютерное приложение.}one{Показать # компьютерное приложение.}few{Показать # компьютерных приложения.}many{Показать # компьютерных приложений.}other{Показать # компьютерного приложения.}}" "%1$s и %2$s" + + + + + + + + diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml index 9d1c3121ae..c1dfa9df78 100644 --- a/quickstep/res/values-si/strings.xml +++ b/quickstep/res/values-si/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}" "{count,plural, =1{# ඩෙස්ක්ටොප් යෙදුමක් පෙන්වන්න.}one{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}other{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}}" "%1$s සහ %2$s" + + + + + + + + diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml index a573b4569a..51f09aa1a8 100644 --- a/quickstep/res/values-sk/strings.xml +++ b/quickstep/res/values-sk/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}" "{count,plural, =1{Zobraziť # aplikáciu pre počítač.}few{Zobraziť # aplikácie pre počítač.}many{Show # desktop apps.}other{Zobraziť # aplikácií pre počítač.}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml index 355dc61464..ea1fd45cbe 100644 --- a/quickstep/res/values-sl/strings.xml +++ b/quickstep/res/values-sl/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}" "{count,plural, =1{Prikaz # aplikacije za namizni računalnik.}one{Prikaz # aplikacije za namizni računalnik.}two{Prikaz # aplikacij za namizni računalnik.}few{Prikaz # aplikacij za namizni računalnik.}other{Prikaz # aplikacij za namizni računalnik.}}" "%1$s in %2$s" + + + + + + + + diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml index 71eca07288..6cc894a2d0 100644 --- a/quickstep/res/values-sq/strings.xml +++ b/quickstep/res/values-sq/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}" "{count,plural, =1{Shfaq # aplikacion për desktop.}other{Shfaq # aplikacione për desktop.}}" "%1$s dhe %2$s" + + + + + + + + diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml index 34bcb1c28e..7828868511 100644 --- a/quickstep/res/values-sr/strings.xml +++ b/quickstep/res/values-sr/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}" "{count,plural, =1{Прикажи # апликацију за рачунаре.}one{Прикажи # апликацију за рачунаре.}few{Прикажи # апликације за рачунаре.}other{Прикажи # апликација за рачунаре.}}" "%1$s и %2$s" + + + + + + + + diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index 723cb82797..4fecddd977 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Visa # app till.}other{Visa # appar till.}}" "{count,plural, =1{Visa # datorapp.}other{Visa # datorappar.}}" "%1$s och %2$s" + + + + + + + + diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml index 6a3f624576..3c4e5e538d 100644 --- a/quickstep/res/values-sw/strings.xml +++ b/quickstep/res/values-sw/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}" "{count,plural, =1{Onyesha programu # ya kompyuta ya mezani.}other{Onyesha programu # za kompyuta ya mezani.}}" "%1$s na %2$s" + + + + + + + + diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml index 90ff5eaa0c..b259dbf124 100644 --- a/quickstep/res/values-ta/strings.xml +++ b/quickstep/res/values-ta/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}" "{count,plural, =1{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}other{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}}" "%1$s மற்றும் %2$s" + + + + + + + + diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index c32f360592..20fc77da8b 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{మరో # యాప్‌ను చూడండి.}other{మరో # యాప్‌లను చూడండి.}}" "{count,plural, =1{# డెస్క్‌టాప్ యాప్‌ను చూపండి.}other{# డెస్క్‌టాప్ యాప్‌లను చూపండి.}}" "%1$s, %2$s" + + + + + + + + diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml index f1fd49b25b..4adcc525cb 100644 --- a/quickstep/res/values-th/strings.xml +++ b/quickstep/res/values-th/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}" "{count,plural, =1{แสดงแอปบนเดสก์ท็อป # รายการ}other{แสดงแอปบนเดสก์ท็อป # รายการ}}" "%1$s และ %2$s" + + + + + + + + diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml index f0e231166d..66ecc00a6c 100644 --- a/quickstep/res/values-tl/strings.xml +++ b/quickstep/res/values-tl/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}" "{count,plural, =1{Ipakita ang # desktop app.}one{Ipakita ang # desktop app.}other{Ipakita ang # na desktop app.}}" "%1$s at %2$s" + + + + + + + + diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml index 5eb84d65f3..dc5fa6bca7 100644 --- a/quickstep/res/values-tr/strings.xml +++ b/quickstep/res/values-tr/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}" "{count,plural, =1{# masaüstü uygulamasını göster.}other{# masaüstü uygulamasını göster.}}" "%1$s ve %2$s" + + + + + + + + diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml index 3be16279ed..5119e565de 100644 --- a/quickstep/res/values-uk/strings.xml +++ b/quickstep/res/values-uk/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}" "{count,plural, =1{Показати # комп’ютерну програму.}one{Показати # комп’ютерну програму.}few{Показати # комп’ютерні програми.}many{Показати # комп’ютерних програм.}other{Показати # комп’ютерної програми.}}" "%1$s та %2$s" + + + + + + + + diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml index 0e951f074b..c42a601758 100644 --- a/quickstep/res/values-ur/strings.xml +++ b/quickstep/res/values-ur/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}" "{count,plural, =1{# ڈیسک ٹاپ ایپ دکھائیں۔}other{# ڈیسک ٹاپ ایپس دکھائیں۔}}" "%1$s اور %2$s" + + + + + + + + diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml index 4d57b2248d..810c8f04b3 100644 --- a/quickstep/res/values-uz/strings.xml +++ b/quickstep/res/values-uz/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}" "{count,plural, =1{# ta desktop ilovani chiqarish.}other{# ta desktop ilovani chiqarish.}}" "%1$s va %2$s" + + + + + + + + diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml index df8ccdca0c..8291ac7552 100644 --- a/quickstep/res/values-vi/strings.xml +++ b/quickstep/res/values-vi/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}" "{count,plural, =1{Hiện # ứng dụng dành cho máy tính.}other{Hiện # ứng dụng dành cho máy tính.}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index e7507308c3..e00e932f2b 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}" "{count,plural, =1{显示 # 款桌面应用。}other{显示 # 款桌面应用。}}" "%1$s%2$s" + + + + + + + + diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index 9427b07e9a..3a7736979c 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}" "{count,plural, =1{顯示 # 個桌面應用程式。}other{顯示 # 個桌面應用程式。}}" "「%1$s」和「%2$s」" + + + + + + + + diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index 3b06edad15..3b5996698f 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{再多顯示 # 個應用程式。}other{再多顯示 # 個應用程式。}}" "{count,plural, =1{顯示 # 個電腦版應用程式。}other{顯示 # 個電腦版應用程式。}}" "「%1$s」和「%2$s」" + + + + + + + + diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml index cb216fc6a6..b3ef1e7199 100644 --- a/quickstep/res/values-zu/strings.xml +++ b/quickstep/res/values-zu/strings.xml @@ -140,4 +140,12 @@ "{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}" "{count,plural, =1{Bonisa i-app engu-# yedeskithophu.}one{Bonisa ama-app angu-# wedeskithophu.}other{Bonisa ama-app angu-# wedeskithophu.}}" "I-%1$s ne-%2$s" + + + + + + + + From ecd70fc3c52957ba8df57a556e77abb79a578878 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 6 Jun 2024 14:20:32 -0700 Subject: [PATCH 066/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I4a743d129b6d2801fa660224e8e881068e267346 --- quickstep/res/values-et/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml index d1b5bfc005..68e566388c 100644 --- a/quickstep/res/values-et/strings.xml +++ b/quickstep/res/values-et/strings.xml @@ -72,7 +72,7 @@ "Pühkige kindlasti ekraani alumisest servast üles." "Hoidke sõrme aknal pisut kauem, enne kui vabastate" "Pühkige kindlasti otse üles, seejärel peatuge" - "Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage seaded." + "Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage Seaded." "Tegite rakenduste vahel vahetamise liigutuse" "Pühkige rakenduste vahetamiseks" "Rakenduste vahel vahetamiseks pühkige ekraanikuva alaosast üles, hoidke ja seejärel vabastage." From 1bd0ffcbeaaaaba661765ee4ceddc1fb10a634ca Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 6 Jun 2024 14:21:29 -0700 Subject: [PATCH 067/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: If11da63842a10196a76325d4d45cbfc626a26108 --- res/values-af/strings.xml | 4 +--- res/values-am/strings.xml | 4 +--- res/values-ar/strings.xml | 4 +--- res/values-as/strings.xml | 4 +--- res/values-az/strings.xml | 4 +--- res/values-b+sr+Latn/strings.xml | 1 - res/values-be/strings.xml | 4 +--- res/values-bg/strings.xml | 4 +--- res/values-bn/strings.xml | 4 +--- res/values-bs/strings.xml | 4 +--- res/values-ca/strings.xml | 4 +--- res/values-cs/strings.xml | 4 +--- res/values-da/strings.xml | 4 +--- res/values-de/strings.xml | 4 +--- res/values-el/strings.xml | 4 +--- res/values-en-rAU/strings.xml | 4 +--- res/values-en-rCA/strings.xml | 1 - res/values-en-rGB/strings.xml | 4 +--- res/values-en-rIN/strings.xml | 4 +--- res/values-en-rXC/strings.xml | 1 - res/values-es-rUS/strings.xml | 4 +--- res/values-es/strings.xml | 4 +--- res/values-et/strings.xml | 1 - res/values-eu/strings.xml | 4 +--- res/values-fa/strings.xml | 4 +--- res/values-fi/strings.xml | 4 +--- res/values-fr-rCA/strings.xml | 4 +--- res/values-fr/strings.xml | 4 +--- res/values-gl/strings.xml | 4 +--- res/values-gu/strings.xml | 4 +--- res/values-hi/strings.xml | 4 +--- res/values-hr/strings.xml | 4 +--- res/values-hu/strings.xml | 4 +--- res/values-hy/strings.xml | 4 +--- res/values-in/strings.xml | 4 +--- res/values-is/strings.xml | 4 +--- res/values-it/strings.xml | 4 +--- res/values-iw/strings.xml | 4 +--- res/values-ja/strings.xml | 1 - res/values-ka/strings.xml | 1 - res/values-kk/strings.xml | 4 +--- res/values-km/strings.xml | 4 +--- res/values-kn/strings.xml | 4 +--- res/values-ko/strings.xml | 4 +--- res/values-ky/strings.xml | 4 +--- res/values-lo/strings.xml | 4 +--- res/values-lt/strings.xml | 1 - res/values-lv/strings.xml | 4 +--- res/values-mk/strings.xml | 4 +--- res/values-ml/strings.xml | 4 +--- res/values-mn/strings.xml | 4 +--- res/values-mr/strings.xml | 1 - res/values-ms/strings.xml | 4 +--- res/values-my/strings.xml | 1 - res/values-nb/strings.xml | 4 +--- res/values-ne/strings.xml | 4 +--- res/values-nl/strings.xml | 4 +--- res/values-or/strings.xml | 4 +--- res/values-pa/strings.xml | 4 +--- res/values-pl/strings.xml | 4 +--- res/values-pt-rPT/strings.xml | 1 - res/values-pt/strings.xml | 4 +--- res/values-ro/strings.xml | 4 +--- res/values-ru/strings.xml | 4 +--- res/values-si/strings.xml | 4 +--- res/values-sk/strings.xml | 4 +--- res/values-sl/strings.xml | 1 - res/values-sq/strings.xml | 4 +--- res/values-sr/strings.xml | 1 - res/values-sv/strings.xml | 4 +--- res/values-sw/strings.xml | 4 +--- res/values-ta/strings.xml | 4 +--- res/values-te/strings.xml | 4 +--- res/values-th/strings.xml | 4 +--- res/values-tl/strings.xml | 4 +--- res/values-tr/strings.xml | 4 +--- res/values-uk/strings.xml | 4 +--- res/values-ur/strings.xml | 4 +--- res/values-uz/strings.xml | 4 +--- res/values-vi/strings.xml | 4 +--- res/values-zh-rCN/strings.xml | 6 ++---- res/values-zh-rHK/strings.xml | 4 +--- res/values-zh-rTW/strings.xml | 4 +--- res/values-zu/strings.xml | 4 +--- 84 files changed, 73 insertions(+), 229 deletions(-) diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index e18d9cd18f..ba507212a4 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -29,8 +29,7 @@ "Tuis" "Verdeelde skerm" "Programinligting vir %1$s" - - + "Gebruikinstellings vir %1$s" "Stoor apppaar" "%1$s | %2$s" "Hierdie apppaar word nie op hierdie toestel gesteun nie" @@ -195,5 +194,4 @@ "Privaat Ruimte-oorgang" "Installeer" "Installeer apps in privaat ruimte" - "Oorvloei" diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index 39dbfef8dc..10d68aa0f1 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -29,8 +29,7 @@ "መነሻ" "የተከፈለ ማያ ገፅ" "የመተግበሪያ መረጃ ለ%1$s" - - + "የ%1$s የአጠቃቀም ቅንብሮች" "የመተግበሪያ ጥምረትን ያስቀምጡ" "%1$s | %2$s" "ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም" @@ -195,5 +194,4 @@ "የግል ቦታ ሽግግር" "ይጫኑ" "መተግበሪያዎችን ወደ የግል ቦታ ይጫኑ" - "ትርፍ ፍሰት" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 1143042949..6ba2ce6085 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -29,8 +29,7 @@ "الشاشة الرئيسية" "تقسيم الشاشة" "‏معلومات تطبيق %1$s" - - + "‏إعدادات استخدام \"%1$s\"" "حفظ استخدام التطبيقين معًا" "%1$s | ‏%2$s" "لا يمكن استخدام هذين التطبيقَين في الوقت نفسه على هذا الجهاز" @@ -195,5 +194,4 @@ "النقل إلى المساحة الخاصة" "تثبيت" "تثبيت التطبيقات في المساحة الخاصّة" - "القائمة الكاملة" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index ed4bb975ae..ce86039da1 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -29,8 +29,7 @@ "গৃহ স্ক্ৰীন" "বিভাজিত স্ক্ৰীন" "%1$sৰ বাবে এপৰ তথ্য" - - + "%1$sৰ বাবে ব্যৱহাৰৰ ছেটিং" "এপৰ পেয়াৰ ছেভ কৰক" "%1$s | %2$s" "এই ডিভাইচটোত এই এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো সমৰ্থিত নহয়" @@ -195,5 +194,4 @@ "ব্যক্তিগত স্পে’চৰ স্থানান্তৰণ" "ইনষ্টল কৰক" "এপ্‌সমূহ প্ৰাইভেট স্পেচত ইনষ্টল কৰক" - "অ’ভাৰফ্ল’" diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index e8273423af..9ad053a2f7 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -29,8 +29,7 @@ "Əsas səhifə" "Ekran bölünməsi" "%1$s ilə bağlı tətbiq məlumatı" - - + "%1$s üzrə istifadə ayarları" "Tətbiq cütünü saxlayın" "%1$s | %2$s" "Bu tətbiq cütü bu cihazda dəstəklənmir" @@ -195,5 +194,4 @@ "Şəxsi məkana keçid" "Quraşdırın" "Tətbiqləri şəxsi sahədə quraşdırın" - "Kənara çıxma" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 30ba09ce2b..408a4258b8 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -194,5 +194,4 @@ "Prenos privatnog prostora" "Instalirajte" "Instaliraj aplikacije u privatan prostor" - "Preklopno" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 3ece170259..c7ed9d926d 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -29,8 +29,7 @@ "Галоўны экран" "Падзелены экран" "Інфармацыя пра праграму для: %1$s" - - + "%1$s: налады выкарыстання" "Захаваць спалучэнне праграм" "%1$s | %2$s" "Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе" @@ -195,5 +194,4 @@ "Пераход у прыватную вобласць" "Усталяваць" "Усталяваць праграмы ў прыватнай прасторы" - "Дадатковае меню" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 4d23773c3c..ce62054c02 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -29,8 +29,7 @@ "Начален екран" "Разделен екран" "Информация за приложението за %1$s" - - + "Настройки за използването на %1$s" "Запазване на двойката приложения" "%1$s | %2$s" "Тази двойка приложения не се поддържа на устройството" @@ -195,5 +194,4 @@ "Преминаване към частното пространство" "Инсталиране" "Инсталиране на приложения в частно пространство" - "Препълване" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 83f4ba1ac8..a9f4585215 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -29,8 +29,7 @@ "হোম" "স্প্লিট স্ক্রিন" "%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য" - - + "%1$s-এর জন্য ব্যবহারের সেটিংস" "অ্যাপ পেয়ার সেভ করুন" "%1$s | %2$s" "এই ডিভাইসে এই অ্যাপ পেয়ারটি কাজ করে না" @@ -195,5 +194,4 @@ "ব্যক্তিগত স্পেস ট্রানজিট করা" "ইনস্টল করুন" "প্রাইভেট স্পেসে অ্যাপ ইনস্টল করুন" - "ওভারফ্লো" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 2c5e22a601..e838b29b75 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -29,8 +29,7 @@ "Početni ekran" "Podijeljeni ekran" "Informacije o aplikaciji %1$s" - - + "Postavke korištenja za: %1$s" "Sačuvaj par aplikacija" "%1$s | %2$s" "Par aplikacija nije podržan na uređaju" @@ -195,5 +194,4 @@ "Prelazak u privatan prostor" "Instaliraj" "Instaliranje aplikacija u privatni prostor" - "Preklopni meni" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index f275e49ee9..50ded7ba8b 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -29,8 +29,7 @@ "Inici" "Pantalla dividida" "Informació de l\'aplicació %1$s" - - + "Configuració d\'ús de %1$s" "Desa la parella d\'aplicacions" "%1$s | %2$s" "Aquesta parella d\'aplicacions no s\'admet en aquest dispositiu" @@ -195,5 +194,4 @@ "Canvia a Espai privat" "Instal·la" "Instal·la les aplicacions a Espai privat" - "Menú addicional" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index c499a9a00a..c570ef13fa 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -29,8 +29,7 @@ "Domů" "Rozdělit obrazovku" "Informace o aplikaci %1$s" - - + "Nastavení využití pro aplikaci %1$s" "Uložit dvojici aplikací" "%1$s | %2$s" "Tento pár aplikací není na tomto zařízení podporován" @@ -195,5 +194,4 @@ "Převádění soukromého prostoru" "Instalovat" "Instalovat aplikace do soukromého prostoru" - "Rozbalovací nabídka" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index f2c08fafbd..e6f741f6e9 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -29,8 +29,7 @@ "Startskærm" "Opdel skærm" "Appinfo for %1$s" - - + "Indstillinger for brug af %1$s" "Gem appsammenknytning" "%1$s | %2$s" "Denne appsammenknytning understøttes ikke på enheden" @@ -195,5 +194,4 @@ "Ændringer af tilstanden for det private område" "Installer" "Installer apps i privat område" - "Overløb" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index f5ecf59e19..ec2285d8be 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -29,8 +29,7 @@ "Startbildschirm" "Splitscreen" "App-Info für %1$s" - - + "Nutzungseinstellungen für %1$s" "App-Paar speichern" "%1$s | %2$s" "Dieses App-Paar wird auf diesem Gerät nicht unterstützt" @@ -195,5 +194,4 @@ "Sperrzustand des vertraulichen Profils wird gerade geändert" "Installieren" "Apps im vertraulichen Profil installieren" - "Weitere Optionen" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 1c4700a86e..8ace970859 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -29,8 +29,7 @@ "Αρχική οθόνη" "Διαχωρισμός οθόνης" "Πληροφορίες εφαρμογής για %1$s" - - + "Ρυθμίσεις χρήσης για %1$s" "Αποθήκευση ζεύγους εφαρμογών" "%1$s | %2$s" "Αυτό το ζεύγος εφαρμογών δεν υποστηρίζεται σε αυτή τη συσκευή" @@ -195,5 +194,4 @@ "Μετάβαση στον Ιδιωτικό χώρο" "Εγκατάσταση" "Εγκατάσταση εφαρμογών στον ιδιωτικό χώρο" - "Υπερχείλιση" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 27bcb658ae..3fe69cd5b7 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -29,8 +29,7 @@ "Home" "Split screen" "App info for %1$s" - - + "Usage settings for %1$s" "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" @@ -195,5 +194,4 @@ "Private Space transitioning" "Install" "Install apps to private space" - "Overflow" diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index f672a827d5..dee4a30029 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -194,5 +194,4 @@ "Private Space Transitioning" "Install" "Install apps to Private Space" - "Overflow" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 27bcb658ae..3fe69cd5b7 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -29,8 +29,7 @@ "Home" "Split screen" "App info for %1$s" - - + "Usage settings for %1$s" "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" @@ -195,5 +194,4 @@ "Private Space transitioning" "Install" "Install apps to private space" - "Overflow" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 27bcb658ae..3fe69cd5b7 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -29,8 +29,7 @@ "Home" "Split screen" "App info for %1$s" - - + "Usage settings for %1$s" "Save app pair" "%1$s | %2$s" "This app pair isn\'t supported on this device" @@ -195,5 +194,4 @@ "Private Space transitioning" "Install" "Install apps to private space" - "Overflow" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index 706c65c525..69added946 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -194,5 +194,4 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎Private Space Transitioning‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎Install‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎Install apps to Private Space‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎Overflow‎‏‎‎‏‎" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 3ba7ece050..75b697930f 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -29,8 +29,7 @@ "Pantalla principal" "Pantalla dividida" "Información de la app de %1$s" - - + "Configuración del uso de %1$s" "Guardar vinculación" "%1$s | %2$s" "No se admite esta vinculación de apps en este dispositivo" @@ -195,5 +194,4 @@ "Pasar a Espacio privado" "Instalar" "Instala las apps en el espacio privado" - "Ampliada" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 7309e58e6f..91e05a76b4 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -29,8 +29,7 @@ "Inicio" "Pantalla dividida" "Información de la aplicación %1$s" - - + "Ajustes de uso para %1$s" "Guardar apps emparejadas" "%1$s | %2$s" "El dispositivo no admite esta aplicación emparejada" @@ -195,5 +194,4 @@ "Cambiar a espacio privado" "Instalar" "Descargar aplicaciones en el espacio privado" - "Desplegable" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 13500b593b..4ad9c9e13e 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -194,5 +194,4 @@ "Privaatse ruumi üleviimine" "Installi" "Rakenduste installimine privaatses ruumis" - "Ületäide" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index d1ff4347aa..8e68ebdc5a 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -29,8 +29,7 @@ "Orri nagusia" "Pantaila zatitzea" "%1$s aplikazioari buruzko informazioa" - - + "%1$s aplikazioaren erabilera-ezarpenak" "Gorde aplikazio parea" "%1$s | %2$s" "Aplikazio pare hori ez da onartzen gailu honetan" @@ -195,5 +194,4 @@ "Eremu pribaturako trantsizioa" "Instalatu" "Instalatu aplikazioak eremu pribatuan" - "Luzapena" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 367945b13c..a19134090a 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -29,8 +29,7 @@ "صفحه اصلی" "صفحهٔ دونیمه" "‏اطلاعات برنامه %1$s" - - + "‏تنظیمات مصرف برای %1$s" "ذخیره جفت برنامه" "%1$s | %2$s" "از این جفت برنامه در این دستگاه پشتیبانی نمی‌شود" @@ -195,5 +194,4 @@ "انتقال «فضای خصوصی»" "نصب" "نصب برنامه‌ها در «فضای خصوصی»" - "سرریز" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 5f7df00ceb..5ff367e70c 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -29,8 +29,7 @@ "Etusivu" "Jaettu näyttö" "Sovellustiedot: %1$s" - - + "Käyttöasetus tälle: %1$s" "Tallenna sovelluspari" "%1$s | %2$s" "Sovellusparia ei tueta tällä laitteella" @@ -195,5 +194,4 @@ "Yksityisen tilan siirtäminen" "Asenna" "Asenna sovelluksia yksityiseen tilaan" - "Ylivuoto" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 9775dbcc5a..daa4b5fb94 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -29,8 +29,7 @@ "Accueil" "Écran divisé" "Renseignements sur l\'appli pour %1$s" - - + "Paramètres d\'utilisation pour %1$s" "Enr. paire d\'applis" "%1$s | %2$s" "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" @@ -195,5 +194,4 @@ "Transition vers l\'Espace privé" "Installer" "Installer des applications dans l\'Espace privé" - "Menu à développer" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 53a30d317d..0ea277b1f2 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -29,8 +29,7 @@ "Accueil" "Écran partagé" "Infos sur l\'appli pour %1$s" - - + "Paramètres d\'utilisation pour %1$s" "Enregistrer la paire d\'applis" "%1$s | %2$s" "Cette paire d\'applications n\'est pas prise en charge sur cet appareil" @@ -195,5 +194,4 @@ "Transition vers Espace privé" "Installer" "Installer des applis dans l\'espace privé" - "Dépassement" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index d651692509..fc667bc91a 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -29,8 +29,7 @@ "Inicio" "Pantalla dividida" "Información da aplicación para %1$s" - - + "Configuración de uso para %1$s" "Gardar parella de apps" "%1$s | %2$s" "O dispositivo non admite este emparellamento de aplicacións" @@ -195,5 +194,4 @@ "Transición ao espazo privado" "Instalar" "Instalar as aplicacións no espazo privado" - "Menú adicional" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 89291bda88..ce411e62db 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -29,8 +29,7 @@ "હોમ સ્ક્રીન" "સ્ક્રીનને વિભાજિત કરો" "%1$s માટે ઍપ માહિતી" - - + "%1$sના વપરાશ સંબંધિત સેટિંગ" "ઍપની જોડી સાચવો" "%1$s | %2$s" "આ ડિવાઇસ પર, આ ઍપની જોડીને સપોર્ટ આપવામાં આવતો નથી" @@ -195,5 +194,4 @@ "ખાનગી સ્પેસ પર સ્થાનાંતરણ" "ઇન્સ્ટૉલ કરો" "ખાનગી સ્પેસમાં ઍપ ઇન્સ્ટૉલ કરો" - "ઓવરફ્લો" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index d70bf08edf..b5042606c5 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -29,8 +29,7 @@ "होम स्क्रीन" "स्प्लिट स्क्रीन" "%1$s के लिए ऐप्लिकेशन की जानकारी" - - + "%1$s के लिए खर्च की सेटिंग" "ऐप पेयर सेव करें" "%1$s | %2$s" "साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन, इस डिवाइस पर काम नहीं कर सकते" @@ -195,5 +194,4 @@ "प्राइवेट स्पेस की सेटिंग में बदलाव किया जा रहा है" "इंस्टॉल करें" "प्राइवेट स्पेस में ऐप्लिकेशन इंस्टॉल करें" - "ओवरफ़्लो" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 19658f6dd1..9d6049524c 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -29,8 +29,7 @@ "Početni zaslon" "Podijeljeni zaslon" "Informacije o aplikaciji %1$s" - - + "Postavke upotrebe za %1$s" "Spremi par aplikacija" "%1$s | %2$s" "Taj par aplikacija nije podržan na ovom uređaju" @@ -195,5 +194,4 @@ "Prelazak na privatni prostor" "Instaliraj" "Instaliranje aplikacija u privatni prostor" - "Dodatni izbornik" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 96e4981246..bb39c3374c 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -29,8 +29,7 @@ "Kezdőképernyő" "Osztott képernyő" "Alkalmazásinformáció a következőhöz: %1$s" - - + "A(z) %1$s használati beállításai" "Alkalmazáspár mentése" "%1$s | %2$s" "Ezt az alkalmazáspárt nem támogatja az eszköz" @@ -195,5 +194,4 @@ "Átállás privát területre…" "Telepítés" "Alkalmazások telepítése privát területre" - "Túlcsordulás" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index e2b6d34235..63b935d80a 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -29,8 +29,7 @@ "Հիմնական էկրան" "Տրոհել էկրանը" "Տեղեկություններ %1$s հավելվածի մասին" - - + "Օգտագործման կարգավորումներ (%1$s)" "Պահել հավելվ. զույգը" "%1$s | %2$s" "Հավելվածների զույգը չի աջակցվում այս սարքում" @@ -195,5 +194,4 @@ "Անցում մասնավոր տարածք" "Տեղադրել" "Հավելվածների տեղադրում անձնական տարածքում" - "Լրացուցիչ ընտրացանկ" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index a86380e5da..ca30b42e94 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -29,8 +29,7 @@ "Layar utama" "Layar terpisah" "Info aplikasi untuk %1$s" - - + "Setelan penggunaan untuk %1$s" "Simpan pasangan aplikasi" "%1$s | %2$s" "Pasangan aplikasi ini tidak didukung di perangkat ini" @@ -195,5 +194,4 @@ "Ruang Pribadi Bertransisi" "Instal" "Instal aplikasi ke Ruang Pribadi" - "Menu tambahan" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index d903d1ae20..aadb75ed93 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -29,8 +29,7 @@ "Heim" "Skipta skjá" "Upplýsingar um forrit fyrir %1$s" - - + "Notkunarstillingar fyrir %1$s" "Vista forritapar" "%1$s | %2$s" "Þetta forritapar er ekki stutt í þessu tæki" @@ -195,5 +194,4 @@ "Leynirými að breytast" "Setja upp" "Setja upp forrit í leynirými" - "Yfirflæði" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 3895409034..36950b84f3 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -29,8 +29,7 @@ "Home" "Schermo diviso" "Informazioni sull\'app %1$s" - - + "Impostazioni di utilizzo per %1$s" "Salva coppia di app" "%1$s | %2$s" "Questa coppia di app non è supportata su questo dispositivo" @@ -195,5 +194,4 @@ "Transizione dello Spazio privato in corso…" "Installa" "Installa le app su spazi privati" - "Extra" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index aea1fa65b1..21581c37e6 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -29,8 +29,7 @@ "בית" "מסך מפוצל" "‏פרטים על האפליקציה %1$s" - - + "‏הגדרות שימוש ב-%1$s" "שמירת צמד אפליקציות" "%1$s | %2$s" "צמד האפליקציות הזה לא נתמך במכשיר הזה" @@ -195,5 +194,4 @@ "מעבר למרחב הפרטי" "התקנה" "התקנת אפליקציות במרחב הפרטי" - "אפשרויות נוספות" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index c349e546b3..1f8a93fc1c 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -194,5 +194,4 @@ "プライベート スペース移行中" "インストール" "プライベート スペースにアプリをインストールします" - "オーバーフロー" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index fecd50e19b..eac12be501 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -194,5 +194,4 @@ "პირად სივრცეზე გადასვლა" "ინსტალაცია" "კერძო სივრცეში აპების ინსტალაცია" - "გადავსება" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index f3aa5f67e7..383a50785b 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -29,8 +29,7 @@ "Негізгі экран" "Экранды бөлу" "%1$s қолданбасы туралы ақпарат" - - + "%1$s пайдалану параметрлері" "Қолданбаларды жұптау әрекетін сақтау" "%1$s | %2$s" "Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды." @@ -195,5 +194,4 @@ "Жеке бөлмеге өту" "Орнату" "Қолданбаларды \"Құпия кеңістікке\" орнатыңыз." - "Қосымша мәзір" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index 1f73d4c25d..e31985256d 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -29,8 +29,7 @@ "អេក្រង់ដើម" "មុខងារ​បំបែកអេក្រង់" "ព័ត៌មានកម្មវិធី​សម្រាប់ %1$s" - - + "ការកំណត់ការប្រើប្រាស់សម្រាប់ %1$s" "រក្សាទុកគូកម្មវិធី" "%1$s | %2$s" "មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ" @@ -195,5 +194,4 @@ "ការផ្លាស់ប្ដូរ Private Space" "ដំឡើង" "ដំឡើងកម្មវិធីទៅលំហឯកជន" - "ម៉ឺនុយបន្ថែម" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 309a1fb431..758d47c518 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -29,8 +29,7 @@ "ಹೋಮ್" "ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್" "%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ" - - + "%1$s ಗೆ ಸಂಬಂಧಿಸಿದ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ಆ್ಯಪ್ ಪೇರ್ ಸೇವ್ ಮಾಡಿ" "%1$s | %2$s" "ಈ ಆ್ಯಪ್ ಜೋಡಿಯು ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ" @@ -195,5 +194,4 @@ "ಖಾಸಗಿ ಸ್ಪೇಸ್ ಪರಿವರ್ತನೆಯಾಗುತ್ತಿದೆ" "ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" "ಆ್ಯಪ್‌ಗಳನ್ನು ಪ್ರೈವೇಟ್ ಸ್ಪೇಸ್‌ನಲ್ಲಿ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" - "ಓವರ್‌ಫ್ಲೋ" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index cfc04ef4a7..4d623fa30b 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -29,8 +29,7 @@ "홈" "화면 분할" "%1$s 앱 정보" - - + "%1$s의 사용량 설정" "앱 페어링 저장" "%1$s | %2$s" "이 앱 페어링은 이 기기에서 지원되지 않습니다" @@ -195,5 +194,4 @@ "비공개 스페이스 전환" "설치" "비공개 스페이스에 앱 설치" - "오버플로" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 96446e88a1..98d1e73439 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -29,8 +29,7 @@ "Башкы экран" "Экранды бөлүү" "%1$s колдонмосу жөнүндө маалымат" - - + "%1$s колдонмосун пайдалануу параметрлери" "Колдонмолорду сактап коюу" "%1$s | %2$s" "Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт" @@ -195,5 +194,4 @@ "Жеке чөйрөгө өтүү" "Орнотуу" "Колдонмолорду Жеке мейкиндикке орнотуe" - "Кошумча меню" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index 708a2f3562..e0bcfe0185 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -29,8 +29,7 @@ "ໂຮມສະກຣີນ" "ແບ່ງໜ້າຈໍ" "ຂໍ້ມູນແອັບສຳລັບ %1$s" - - + "ການຕັ້ງຄ່າການນຳໃຊ້ສຳລັບ %1$s" "ບັນທຶກຈັບຄູ່ແອັບ" "%1$s | %2$s" "ການຈັບຄູ່ແອັບນີ້ບໍ່ຮອງຮັບຢູ່ອຸປະກອນນີ້" @@ -195,5 +194,4 @@ "ການປ່ຽນແປງພື້ນທີ່ສ່ວນຕົວ" "ຕິດຕັ້ງ" "ຕິດຕັ້ງແອັບໄປໃສ່ພື້ນທີ່ສ່ວນບຸກຄົນ" - "ການດຳເນີນການເພີ່ມເຕີມ" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index bc33bd8efd..6a2b8d7f0f 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -194,5 +194,4 @@ "Privačios erdvės perkėlimas" "Įdiegti" "Įdiegti programas privačioje erdvėje" - "Perpildymas" diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 7dbe5facaa..cae6b6e211 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -29,8 +29,7 @@ "Sākums" "Sadalīt ekrānu" "%1$s: informācija par lietotni" - - + "Lietojuma iestatījumi: %1$s" "Saglabāt lietotņu pāri" "%1$s | %2$s" "Šis lietotņu pāris netiek atbalstīts šajā ierīcē" @@ -195,5 +194,4 @@ "Pāriet uz privāto mapi" "Instalēt" "Instalējiet lietotnes privātajā telpā." - "Pārpilde" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 18849e9ce1..46d8600c3d 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -29,8 +29,7 @@ "Почетен екран" "Поделен екран" "Податоци за апликација за %1$s" - - + "Поставки за користење за %1$s" "Зачувај го парот апликации" "%1$s | %2$s" "Паров апликации не е поддржан на уредов" @@ -195,5 +194,4 @@ "Префрлање на „Приватен простор“" "Инсталирајте" "Инсталирање апликации во „Приватен простор“" - "Проширено балонче" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 529cc8d53e..eec5f74a54 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -29,8 +29,7 @@ "ഹോം" "സ്‌ക്രീൻ വിഭജന മോഡ്" "%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ" - - + "%1$s എന്നതിനുള്ള ഉപയോഗ ക്രമീകരണം" "ആപ്പ് ജോടി സംരക്ഷിക്കുക" "%1$s | %2$s" "ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല" @@ -195,5 +194,4 @@ "പ്രൈവറ്റ് സ്‌പേസ് ട്രാൻസിഷനിംഗ്" "ഇൻസ്റ്റാൾ ചെയ്യുക" "സ്വകാര്യ സ്പേസിലേക്ക് ആപ്പുകൾ ഇൻസ്റ്റാൾ ചെയ്യുക" - "ഓവർഫ്ലോ" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 21c8ad15b2..396589c796 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -29,8 +29,7 @@ "Нүүр" "Дэлгэцийг хуваах" "%1$s-н аппын мэдээлэл" - - + "%1$s-н ашиглалтын тохиргоо" "Апп хослуулалтыг хадгалах" "%1$s | %2$s" "Энэ апп хослуулалтыг уг төхөөрөмж дээр дэмждэггүй" @@ -195,5 +194,4 @@ "Private Space-н шилжилт" "Суулгах" "Хувийн орон зайд аппууд суулгана уу" - "Урт цэс" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 1badd2124f..972c9f2342 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -194,5 +194,4 @@ "खाजगी स्पेस वर स्विच करणे" "इंस्टॉल करा" "अ‍ॅप्स खाजगी स्पेस मध्ये इंस्टॉल करा" - "ओव्हरफ्लो" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 270ebf0b68..c25e3df9d6 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -29,8 +29,7 @@ "Rumah" "Skrin pisah" "Maklumat apl untuk %1$s" - - + "Tetapan penggunaan sebanyak %1$s" "Simpan gandingan apl" "%1$s | %2$s" "Gandingan apl ini tidak disokong pada peranti ini" @@ -195,5 +194,4 @@ "Peralihan Ruang Peribadi" "Pasang" "Pasang apl pada Ruang Peribadi" - "Limpahan" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index cec9b1b76c..700278a454 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -194,5 +194,4 @@ "သီးသန့်ချတ်ခန်း အပြောင်းအလဲ" "ထည့်သွင်းရန်" "‘သီးသန့်နေရာ’ တွင် အက်ပ်များ ထည့်သွင်းနိုင်သည်" - "မီနူးအပို" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 392cf45721..c2f99aa052 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -29,8 +29,7 @@ "Startskjerm" "Delt skjerm" "Appinformasjon for %1$s" - - + "Bruksinnstillinger for %1$s" "Lagre apptilkoblingen" "%1$s | %2$s" "Denne apptilkoblingen støttes ikke på denne enheten" @@ -195,5 +194,4 @@ "Private Space-overgang" "Installer" "Installer apper i privat område" - "Overflyt" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index f5a16ee257..5e93f89654 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -29,8 +29,7 @@ "होम" "स्प्लिट स्क्रिन" "%1$s का हकमा एपसम्बन्धी जानकारी" - - + "%1$s को प्रयोगसम्बन्धी सेटिङ" "एपको पेयर सेभ गर्नुहोस्" "%1$s | %2$s" "यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन" @@ -195,5 +194,4 @@ "निजी स्पेस ट्रान्जिसन गरिँदै छ" "इन्स्टल गर्नुहोस्" "निजी स्पेसमा एपहरू इन्स्टल गर्नुहोस्" - "ओभरफ्लो" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 176fbc9bc9..d7d4e7de23 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -29,8 +29,7 @@ "Startscherm" "Gesplitst scherm" "App-info voor %1$s" - - + "Gebruiksinstellingen voor %1$s" "App-paar opslaan" "%1$s | %2$s" "Dit app-paar wordt niet ondersteund op dit apparaat" @@ -195,5 +194,4 @@ "Overschakelen naar privéruimte" "Installeren" "Apps installeren in privégedeelte" - "Overloop" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index db656a6a0f..3c240ae129 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -29,8 +29,7 @@ "ହୋମ" "ସ୍କ୍ରିନ‌କୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ" "%1$s ପାଇଁ ଆପ ସୂଚନା" - - + "%1$s ପାଇଁ ବ୍ୟବହାର ସେଟିଂସ" "ଆପ ପେୟାର ସେଭ କରନ୍ତୁ" "%1$s | %2$s" "ଏହି ଆପ ପେୟାର ଏ ଡିଭାଇସରେ ସମର୍ଥିତ ନୁହେଁ" @@ -195,5 +194,4 @@ "ପ୍ରାଇଭେଟ ସ୍ପେସ ଟ୍ରାଞ୍ଜିସନିଂ" "ଇନଷ୍ଟଲ କରନ୍ତୁ" "ଆପ୍ସକୁ ପ୍ରାଇଭେଟ ସ୍ପେସରେ ଇନଷ୍ଟଲ କରନ୍ତୁ" - "ଓଭରଫ୍ଲୋ" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index a496865c3c..0df0c3f274 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -29,8 +29,7 @@ "ਮੁੱਖ ਪੰਨਾ" "ਸਪਲਿਟ ਸਕ੍ਰੀਨ" "%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ" - - + "%1$s ਲਈ ਵਰਤੋਂ ਸੈਟਿੰਗਾਂ" "ਐਪ ਜੋੜਾਬੱਧ ਰੱਖਿਅਤ ਕਰੋ" "%1$s | %2$s" "ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਦਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਨ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ" @@ -195,5 +194,4 @@ "ਨਿੱਜੀ ਸਪੇਸ ਨੂੰ ਤਬਦੀਲ ਕਰਨਾ" "ਸਥਾਪਤ ਕਰੋ" "ਪ੍ਰਾਈਵੇਟ ਸਪੇਸ ਵਿੱਚ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ" - "ਓਵਰਫ਼ਲੋ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 86a43ab666..a8e79e3a50 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -29,8 +29,7 @@ "Ekran główny" "Podziel ekran" "Informacje o aplikacji: %1$s" - - + "%1$s – ustawienia użycia" "Zapisz parę aplikacji" "%1$s | %2$s" "Ta para aplikacji nie jest obsługiwana na tym urządzeniu" @@ -195,5 +194,4 @@ "Przenoszenie obszaru prywatnego" "Zainstaluj" "Zainstaluj aplikacje w przestrzeni prywatnej" - "Rozwiń menu" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index a8eadfe354..6e4a8e89cb 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -194,5 +194,4 @@ "Transição do espaço privado" "Instalar" "Instale apps no espaço privado" - "Menu adicional" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 2833a3fdb4..a049a80c09 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -29,8 +29,7 @@ "Início" "Tela dividida" "Informações do app %1$s" - - + "Configurações de uso de %1$s" "Salvar par de apps" "%1$s | %2$s" "Este Par de apps não está disponível no dispositivo" @@ -195,5 +194,4 @@ "Espaço particular em transição" "Instalar" "Instalar apps no espaço privado" - "Balão flutuante" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index a3ee56ee3f..bbade3c666 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -29,8 +29,7 @@ "Pagina de pornire" "Ecran împărțit" "Informații despre aplicație pentru %1$s" - - + "Setări de utilizare pentru %1$s" "Salvează perechea de aplicații" "%1$s | %2$s" "Perechea de aplicații nu este acceptată pe acest dispozitiv" @@ -195,5 +194,4 @@ "Tranziție pentru spațiul privat" "Instalează" "Instalează aplicații în Spațiul privat" - "Suplimentar" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 7b99297f4a..995052e8f7 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -29,8 +29,7 @@ "Главный экран" "Разделить экран" "Сведения о приложении \"%1$s\"" - - + "Настройки использования приложения \"%1$s\"" "Сохранить приложения" "%1$s | %2$s" "Одновременно использовать эти два приложения на устройстве нельзя." @@ -195,5 +194,4 @@ "Переход к личному пространству" "Установить" "Установить приложения в личном пространстве" - "Дополнительное меню" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 511d59348c..914085416c 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -29,8 +29,7 @@ "මුල් පිටුව" "බෙදුම් තිරය" "%1$s සඳහා යෙදුම් තතු" - - + "%1$s සඳහා භාවිත සැකසීම්" "යෙදුම් යුගල සුරකින්න" "%1$s | %2$s" "මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි" @@ -195,5 +194,4 @@ "පෞද්ගලික අවකාශ සංක්‍රමණය" "ස්ථාපන කරන්න" "පෞද්ගලික අවකාශයට යෙදුම් ස්ථාපනය කරන්න" - "පිටාර යාම" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 960259425e..1ba5771180 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -29,8 +29,7 @@ "Domov" "Rozdeliť obrazovku" "Informácie o aplikácii pre %1$s" - - + "Nastavenia používania pre %1$s" "Uložiť pár aplikácií" "%1$s | %2$s" "Tento pár aplikácií nie je v tomto zariadení podporovaný" @@ -195,5 +194,4 @@ "Prechod súkromného priestoru" "Inštalovať" "Inštalácia aplikácií v súkromnom priestore" - "Rozšírená ponuka" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 2b334aa2eb..cea6e1832c 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -194,5 +194,4 @@ "Preklapljanje zasebnega prostora" "Namestitev" "Nameščanje aplikacij v zasebni prostor" - "Oblaček z dodatnimi elementi" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index fbeb20537d..f328557dc9 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -29,8 +29,7 @@ "Ekrani bazë" "Ekrani i ndarë" "Informacioni i aplikacionit për %1$s" - - + "Cilësimet e përdorimit për \"%1$s\"" "Ruaj çiftin e aplikacioneve" "%1$s | %2$s" "Ky çift aplikacionesh nuk mbështetet në këtë pajisje" @@ -195,5 +194,4 @@ "Kalimi te \"Hapësira private\"" "Instalo" "Instalo aplikacionet në hapësirën private" - "Tejkalimi" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 8ae58ebb29..6fdeb418c6 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -194,5 +194,4 @@ "Пренос приватног простора" "Инсталирајте" "Инсталирај апликације у приватан простор" - "Преклопно" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index d99fd86bbb..1866f95b02 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -29,8 +29,7 @@ "Startskärm" "Delad skärm" "Appinformation för %1$s" - - + "Användningsinställningar för %1$s" "Spara app-par" "%1$s | %2$s" "De här apparna som ska användas tillsammans stöds inte på den här enheten" @@ -195,5 +194,4 @@ "Överföring av privat rum" "Installera" "Installera appar i privat rum" - "Fler alternativ" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 8893a907cb..5c02beb2f5 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -29,8 +29,7 @@ "Skrini ya kwanza" "Gawa skrini" "Maelezo ya programu ya %1$s" - - + "Mipangilio ya matumizi ya %1$s" "Hifadhi jozi ya programu" "%1$s | %2$s" "Jozi hii ya programu haitumiki kwenye kifaa hiki" @@ -195,5 +194,4 @@ "Mabadiliko ya Nafasi ya Faragha" "Weka" "Sakinisha programu kwenye Sehemu ya Faragha" - "Menyu ya vipengee vya ziada" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index fbd788071b..ebc55caa11 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -29,8 +29,7 @@ "முகப்பு" "திரைப் பிரிப்பு" "%1$sக்கான ஆப்ஸ் தகவல்கள்" - - + "%1$sக்கான உபயோக அமைப்புகள்" "ஆப்ஸ் ஜோடியைச் சேமி" "%1$s | %2$s" "இந்தச் சாதனத்தில் இந்த ஆப்ஸ் ஜோடி ஆதரிக்கப்படவில்லை" @@ -195,5 +194,4 @@ "தனிப்பட்ட சேமிப்பிடத்திற்கு மாற்றுகிறது" "நிறுவுதல்" "தனிப்பட்ட சேமிப்பிடத்தில் ஆப்ஸை நிறுவும்" - "கூடுதல் விருப்பங்களைக் காட்டும்" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 11c2755cb9..e1c4668b0f 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -29,8 +29,7 @@ "మొదటి ట్యాబ్" "స్ప్లిట్ స్క్రీన్" "%1$s కోసం యాప్ సమాచారం" - - + "%1$sకు సంబంధించిన వినియోగ సెట్టింగ్‌లు" "యాప్ పెయిర్‌ను సేవ్ చేయండి" "%1$s | %2$s" "ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు" @@ -195,5 +194,4 @@ "ప్రైవేట్ స్పేస్ కేటాయించడం జరుగుతుంది" "ఇన్‌స్టాల్ చేయండి" "ప్రైవేట్ స్పేస్‌కు యాప్‌లను ఇన్‌స్టాల్ చేయండి" - "ఓవర్‌ఫ్లో" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index d006e5e117..4288c24936 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -29,8 +29,7 @@ "หน้าแรก" "แยกหน้าจอ" "ข้อมูลแอปสำหรับ %1$s" - - + "การตั้งค่าการใช้งานสำหรับ %1$s" "บันทึกคู่แอป" "%1$s | %2$s" "ไม่รองรับคู่แอปนี้ในอุปกรณ์เครื่องนี้" @@ -195,5 +194,4 @@ "การเปลี่ยนไปใช้พื้นที่ส่วนตัว" "ติดตั้ง" "ติดตั้งแอปไปยังพื้นที่ส่วนตัว" - "การดำเนินการเพิ่มเติม" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index a497d4f8d9..305f5322c4 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -29,8 +29,7 @@ "Home" "Split screen" "Impormasyon ng app para sa %1$s" - - + "Mga setting ng paggamit para sa %1$s" "I-save ang app pair" "%1$s | %2$s" "Hindi sinusuportahan sa device na ito ang pares ng app na ito" @@ -195,5 +194,4 @@ "Pag-transition ng Pribadong Space" "I-install" "Mag-install ng mga app sa Pribadong Space" - "Overflow" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 301a754379..0681e3d60a 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -29,8 +29,7 @@ "Ana ekran" "Bölünmüş ekran" "%1$s uygulama bilgileri" - - + "%1$s ile ilgili kullanım ayarları" "Uygulama çiftini kaydedin" "%1$s | %2$s" "Bu uygulama çifti bu cihazda desteklenmiyor" @@ -195,5 +194,4 @@ "Gizli Alana Geçiş" "Yükle" "Uygulamaları özel alana yükleyin" - "Taşma" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 3ff70b8b28..c1d6b2fa85 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -29,8 +29,7 @@ "Головний екран" "Розділити екран" "Інформація про додаток для %1$s" - - + "Параметри використання (%1$s)" "Зберегти пару додатків" "%1$s | %2$s" "Ці два додатки не можна одночасно використовувати на цьому пристрої" @@ -195,5 +194,4 @@ "Перехід у приватний простір" "Установити" "Установити додатки в особистому просторі" - "Додаткове меню" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 653959ea7a..6c1a88e95c 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -29,8 +29,7 @@ "ہوم" "اسپلٹ اسکرین" "‏%1$s کے لیے ایپ کی معلومات" - - + "‏%1$s کیلئے استعمال کی ترتیبات" "ایپس کے جوڑے کو محفوظ کریں" "%1$s | %2$s" "ایپس کا یہ جوڑا اس آلے پر تعاون یافتہ نہیں ہے" @@ -195,5 +194,4 @@ "نجی اسپیس کی منتقلی" "انسٹال کریں" "پرائیویٹ اسپیس میں ایپس انسٹال کریں" - "اوورفلو" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 194822e789..18431cc068 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -29,8 +29,7 @@ "Bosh ekran" "Ekranni ikkiga ajratish" "%1$s ilovasi axboroti" - - + "%1$s uchun sarf sozlamalari" "Ilova juftini saqlash" "%1$s | %2$s" "Bu ilova jufti ushbu qurilmada ishlamaydi" @@ -195,5 +194,4 @@ "Maxfiy joyga almashtirish" "Oʻrnatish" "Ilovalarni Maxfiy makonga oʻrnatish" - "Kengaytirish" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index f50b8e8d9b..b5fb1d7463 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -29,8 +29,7 @@ "Màn hình chính" "Chia đôi màn hình" "Thông tin ứng dụng cho %1$s" - - + "Chế độ cài đặt mức sử dụng %1$s" "Lưu cặp ứng dụng" "%1$s | %2$s" "Cặp ứng dụng này không hoạt động được trên thiết bị này" @@ -195,5 +194,4 @@ "Chuyển đổi sang không gian riêng tư" "Cài đặt" "Cài đặt ứng dụng vào Không gian riêng tư" - "Bong bóng bổ sung" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index b4c432b56a..d51f8fd9c3 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -29,8 +29,7 @@ "主屏幕" "分屏" "%1$s 的应用信息" - - + "%1$s的使用设置" "保存应用组合" "%1$s | %2$s" "在该设备上无法使用此应用对" @@ -88,7 +87,7 @@ "安装到私密个人资料中" "卸载应用" "安装" - "不要提供应用建议" + "不要推荐此应用" "固定预测的应用" "安装快捷方式" "允许应用自行添加快捷方式。" @@ -195,5 +194,4 @@ "私密空间转换" "安装" "将应用安装到私密空间" - "菜单" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 94b3ae6eaa..90ff5151ab 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -29,8 +29,7 @@ "主畫面" "分割螢幕" "%1$s 的應用程式資料" - - + "「%1$s」的用量設定" "儲存應用程式配對" "%1$s | %2$s" "此裝置不支援此應用程式配對" @@ -195,5 +194,4 @@ "轉為「私人空間」" "安裝" "將應用程式安裝在「私人空間」中" - "顯示更多" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index e0b7ab2ea1..023a5265c1 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -29,8 +29,7 @@ "主畫面" "分割畫面" "「%1$s」的應用程式資訊" - - + "「%1$s」的用量設定" "儲存應用程式配對" "%1$s | %2$s" "這部裝置不支援這組應用程式配對" @@ -195,5 +194,4 @@ "轉換私人空間狀態" "安裝" "將應用程式安裝在私人空間中" - "溢位" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 16d71a6da3..a9367250c2 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -29,8 +29,7 @@ "Ikhaya" "Hlukanisa isikrini" "Ulwazi lwe-App ye-%1$s" - - + "Amasethingi okusetshenziswa ka-%1$s" "Londoloza i-app ebhangqiwe" "%1$s | %2$s" "Lokhu kubhanqwa kwe-app akusekelwa kule divayisi" @@ -195,5 +194,4 @@ "Ukuguqulwa Kwendawo Yangasese" "Faka" "Faka ama-app Endaweni Engasese" - "Ukugcwala kakhulu" From 8a174558c201873519557e38a8d1d439587540fe Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 6 Jun 2024 14:21:58 -0700 Subject: [PATCH 068/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I15ce34d1823617c0912bfdae1feb6185483db2f1 --- res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index b00a2659ad..447829b432 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -86,7 +86,7 @@ "应用信息" "安装到私密个人资料中" "安装" - "不要提供应用建议" + "不要推荐此应用" "固定预测的应用" "安装快捷方式" "允许应用自行添加快捷方式。" From d69e21f8fe74738fd2a152daf77523157abdbd9a Mon Sep 17 00:00:00 2001 From: Shamali P Date: Thu, 6 Jun 2024 19:48:03 +0000 Subject: [PATCH 069/143] Ensure widgets from WidgetSections.xml are included in suggestions Additionally, let only prediction system provide suggestions, since the UI surface has been there for a while, adding locally filtered widgets from app package isn't required. Bug: 345520128 Test: Unit tests Flag: EXEMPT bugfix Change-Id: Ia97f0743fefeae750e07a694bb19d24a5cc11ffe --- .../model/WidgetsPredictionUpdateTask.java | 30 ++++++------------- .../WidgetsPredicationUpdateTaskTest.java | 13 ++------ .../android/launcher3/model/WidgetsModel.java | 17 +++++++++++ 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java index 39f2c00c99..64bb05e1ab 100644 --- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java +++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java @@ -19,6 +19,7 @@ import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION; import android.app.prediction.AppTarget; +import android.content.ComponentName; import android.content.Context; import android.text.TextUtils; @@ -29,7 +30,6 @@ import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.QuickstepModelDelegate.PredictorState; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.ComponentKey; -import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.widget.PendingAddWidgetInfo; import com.android.launcher3.widget.picker.WidgetRecommendationCategoryProvider; @@ -64,36 +64,24 @@ public final class WidgetsPredictionUpdateTask implements ModelUpdateTask { widget -> new ComponentKey(widget.providerName, widget.user)).collect( Collectors.toSet()); Predicate notOnWorkspace = w -> !widgetsInWorkspace.contains(w); - Map> allWidgets = - dataModel.widgetsModel.getAllWidgetsWithoutShortcuts(); + Map allWidgets = + dataModel.widgetsModel.getAllWidgetComponentsWithoutShortcuts(); List servicePredictedItems = new ArrayList<>(); - List localFilteredWidgets = new ArrayList<>(); for (AppTarget app : mTargets) { - PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), app.getUser()); - List widgets = allWidgets.get(packageUserKey); - if (widgets == null || widgets.isEmpty()) { + ComponentKey componentKey = new ComponentKey( + new ComponentName(app.getPackageName(), app.getClassName()), app.getUser()); + WidgetItem widget = allWidgets.get(componentKey); + if (widget == null) { continue; } String className = app.getClassName(); if (!TextUtils.isEmpty(className)) { - WidgetItem item = widgets.stream() - .filter(w -> className.equals(w.componentName.getClassName())) - .filter(notOnWorkspace) - .findFirst() - .orElse(null); - if (item != null) { - servicePredictedItems.add(item); - continue; + if (notOnWorkspace.test(widget)) { + servicePredictedItems.add(widget); } } - // No widget was added by the service, try local filtering - widgets.stream().filter(notOnWorkspace).findFirst() - .ifPresent(localFilteredWidgets::add); - } - if (servicePredictedItems.isEmpty()) { - servicePredictedItems.addAll(localFilteredWidgets); } List items; diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java index 8702f70dfe..7b57c81b74 100644 --- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java +++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java @@ -184,7 +184,7 @@ public final class WidgetsPredicationUpdateTaskTest { } @Test - public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty() { + public void widgetsRecommendationRan_shouldReturnEmptyWidgetsWhenEmpty() { runOnExecutorSync(MODEL_EXECUTOR, () -> { // Not installed widget @@ -204,19 +204,12 @@ public final class WidgetsPredicationUpdateTaskTest { newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1))); runOnExecutorSync(MAIN_EXECUTOR, () -> { }); - // THEN only 2 widgets are returned because the launcher only filters out - // non-exist widgets. + // Only widgets suggested by prediction system are returned. List recommendedWidgets = mCallback.mRecommendedWidgets.items .stream() .map(itemInfo -> (PendingAddWidgetInfo) itemInfo) .collect(Collectors.toList()); - assertThat(recommendedWidgets).hasSize(2); - recommendedWidgets.forEach(pendingAddWidgetInfo -> - assertThat(pendingAddWidgetInfo.recommendationCategory).isNotNull() - ); - // Another widget from the same package - assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2); - assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1); + assertThat(recommendedWidgets).hasSize(0); }); } diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java index 5e0edb3139..4cba0b5239 100644 --- a/src/com/android/launcher3/model/WidgetsModel.java +++ b/src/com/android/launcher3/model/WidgetsModel.java @@ -32,6 +32,7 @@ import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.pm.ShortcutConfigActivityInfo; +import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; @@ -129,6 +130,22 @@ public class WidgetsModel { return packagesToWidgets; } + /** + * Returns a map of widget component keys to corresponding widget items. Excludes the + * shortcuts. + */ + public synchronized Map getAllWidgetComponentsWithoutShortcuts() { + if (!WIDGETS_ENABLED) { + return Collections.emptyMap(); + } + Map widgetsMap = new HashMap<>(); + mWidgetsList.forEach((packageItemInfo, widgetsAndShortcuts) -> + widgetsAndShortcuts.stream().filter(item -> item.widgetInfo != null).forEach( + item -> widgetsMap.put(new ComponentKey(item.componentName, item.user), + item))); + return widgetsMap; + } + /** * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise * only widgets and shortcuts associated with the package/user are. From 410681a9556d334d827de74b30a566ad516dbb09 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 6 Jun 2024 15:32:33 -0700 Subject: [PATCH 070/143] Ensure starting position rect isn't empty in FloatingTaskView * on rotation taskbar re-inflates it's hotseat views. If we're already in split, then FloatingTaskView tries to do calculations on the view's position in the window, but has a reference to the old, pre-rotated view which is no longer in any window. * This sets startingPosition to be an empty rect, which is used to set LayoutParam values, which are used downstream in update() to calculate scale, and thus we end up dividing by 0. * TODO(b/345556328) figure out a better solution than checking for an empty rect Fixes: 342606096 Test: Repro steps don't cause crash Flag: EXEMPT bugfix Change-Id: Icb546a05d383d1997a92471fc1de3ffc37d06eca --- .../src/com/android/quickstep/views/FloatingTaskView.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index 0e451b5800..acbb2eccbb 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -187,7 +187,13 @@ public class FloatingTaskView extends FrameLayout { viewBounds, false /* ignoreTransform */, null /* recycle */, mStartingPosition); } - + // In some cases originalView is off-screen so we don't get a valid starting position + // ex. on rotation + // TODO(b/345556328) We shouldn't be animating if starting position of view isn't ready + if (mStartingPosition.isEmpty()) { + // Set to non empty for now so calculations in #update() don't break + mStartingPosition.set(0, 0, 1, 1); + } final BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams( Math.round(mStartingPosition.width()), Math.round(mStartingPosition.height())); From 277a4f9d7839278562dcac311418027cbf7bd7c5 Mon Sep 17 00:00:00 2001 From: Shamali P Date: Thu, 6 Jun 2024 20:19:52 +0000 Subject: [PATCH 071/143] Use just the preview for drag and drop in the standalone activity Bug: N/A Test: Manual Flag: EXEMPT bugfix Change-Id: I62c42b649e720826979123ae2ff6c5e238fe59dc --- .../src/com/android/launcher3/WidgetPickerActivity.java | 9 +++++++-- src/com/android/launcher3/widget/WidgetCell.java | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java index 23cb8e9baa..943c08c786 100644 --- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java +++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java @@ -194,6 +194,11 @@ public class WidgetPickerActivity extends BaseActivity { return false; } + View dragView = widgetCell.getDragAndDropView(); + if (dragView == null) { + return false; + } + ClipData clipData = new ClipData( new ClipDescription( /* label= */ "", // not displayed anywhere; so, set to empty. @@ -209,9 +214,9 @@ public class WidgetPickerActivity extends BaseActivity { .putExtra(EXTRA_IS_PENDING_WIDGET_DRAG, true)); // DRAG_FLAG_GLOBAL permits dragging data beyond app window. - return view.startDragAndDrop( + return dragView.startDragAndDrop( clipData, - new View.DragShadowBuilder(view), + new View.DragShadowBuilder(dragView), /* myLocalState= */ null, View.DRAG_FLAG_GLOBAL ); diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index 2bb485aafa..35372d3af5 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -372,6 +372,13 @@ public class WidgetCell extends LinearLayout { } } + /** + * Returns a view (holding the previews) that can be dragged and dropped. + */ + public View getDragAndDropView() { + return mWidgetImageContainer; + } + public WidgetImageView getWidgetView() { return mWidgetImage; } From f8efb32379536695fcc3aa3041917eb4906d08dc Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 6 Jun 2024 15:32:33 -0700 Subject: [PATCH 072/143] Ensure starting position rect isn't empty in FloatingTaskView * on rotation taskbar re-inflates it's hotseat views. If we're already in split, then FloatingTaskView tries to do calculations on the view's position in the window, but has a reference to the old, pre-rotated view which is no longer in any window. * This sets startingPosition to be an empty rect, which is used to set LayoutParam values, which are used downstream in update() to calculate scale, and thus we end up dividing by 0. * TODO(b/345556328) figure out a better solution than checking for an empty rect Fixes: 342606096 Test: Repro steps don't cause crash Flag: EXEMPT bugfix Change-Id: Icb546a05d383d1997a92471fc1de3ffc37d06eca Merged-In: Icb546a05d383d1997a92471fc1de3ffc37d06eca (cherry picked from commit 410681a9556d334d827de74b30a566ad516dbb09) --- .../src/com/android/quickstep/views/FloatingTaskView.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index 5eebc3e285..0ed0a2942e 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -189,7 +189,13 @@ public class FloatingTaskView extends FrameLayout { viewBounds, false /* ignoreTransform */, null /* recycle */, mStartingPosition); } - + // In some cases originalView is off-screen so we don't get a valid starting position + // ex. on rotation + // TODO(b/345556328) We shouldn't be animating if starting position of view isn't ready + if (mStartingPosition.isEmpty()) { + // Set to non empty for now so calculations in #update() don't break + mStartingPosition.set(0, 0, 1, 1); + } final BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams( Math.round(mStartingPosition.width()), Math.round(mStartingPosition.height())); From 669b9c5c30181b3ae171d9e336848c8390fbe270 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 5 Jun 2024 17:37:02 +0000 Subject: [PATCH 073/143] Always report mandatory insets for button nav Fixes: 340134342 Fixes: 343817842 Test: atest android.systemui.cts.WindowInsetsBehaviorTests Test: Verify mandatory insets vs window bounds in various orientations when folded/unfolded Change-Id: I18d4f5d212d16c62d15d84b4842b3d20c0d8c5ae Merged-In: I18d4f5d212d16c62d15d84b4842b3d20c0d8c5ae (cherry picked from commit 762b3b4685225cbb2b106ac2c82ced50e19404cc) --- .../com/android/launcher3/taskbar/TaskbarInsetsController.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 4f511c1bfd..175306a574 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -223,7 +223,8 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, endRotation) } else if (provider.type == mandatorySystemGestures()) { if (context.isThreeButtonNav) { - provider.insetsSize = Insets.of(0, 0, 0, 0) + provider.insetsSize = getInsetsForGravityWithCutout(contentHeight, gravity, + endRotation) } else { val gestureHeight = ResourceUtils.getNavbarSize( From 0d934c47e538ac041f6b096495a71eb9b8808e8b Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 6 Jun 2024 19:28:05 +0100 Subject: [PATCH 074/143] Add test for UserBadgeDrawable alpha handling Fix: 316576459 Test: UserBadgeDrawableTest Flag: EXEMPT bugfix Change-Id: I3819855f8cac24176ea734bd6a0ac7bffd17e900 --- .../launcher3/icons/UserBadgeDrawableTest.kt | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt diff --git a/tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt b/tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt new file mode 100644 index 0000000000..d611ae8dd6 --- /dev/null +++ b/tests/multivalentTests/src/com/android/launcher3/icons/UserBadgeDrawableTest.kt @@ -0,0 +1,76 @@ +/* + * 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.icons + +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.android.launcher3.icons.UserBadgeDrawable.SHADOW_COLOR +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +/** Test for [UserBadgeDrawable] */ +@RunWith(AndroidJUnit4::class) +class UserBadgeDrawableTest { + private val context = InstrumentationRegistry.getInstrumentation().targetContext + private val canvas = mock() + private val systemUnderTest = + UserBadgeDrawable(context, R.drawable.ic_work_app_badge, R.color.badge_tint_work, false) + + @Test + fun draw_opaque() { + val colorList = mutableListOf() + whenever( + canvas.drawCircle( + any(), + any(), + any(), + any() + ) + ).then { colorList.add(it.getArgument(3).color) } + + systemUnderTest.alpha = 255 + systemUnderTest.draw(canvas) + + assertThat(colorList).containsExactly(SHADOW_COLOR, Color.WHITE) + } + + @Test + fun draw_transparent() { + val colorList = mutableListOf() + whenever( + canvas.drawCircle( + any(), + any(), + any(), + any() + ) + ).then { colorList.add(it.getArgument(3).color) } + + systemUnderTest.alpha = 0 + systemUnderTest.draw(canvas) + + assertThat(colorList).hasSize(2) + assertThat(Color.valueOf(colorList[0]).alpha()).isEqualTo(0) + assertThat(Color.valueOf(colorList[1]).alpha()).isEqualTo(0) + } +} From f7c9466c8f2ddc394e3e914995666b1c9d869b37 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 7 Jun 2024 15:57:26 +0100 Subject: [PATCH 075/143] Reserve space for system bars in both orientations in fake orientation - In BaseContainerInterface.calculateTaskSize, combine both portrait and landscape/seascape insets to leave space for status bar/nav bar in either orientations. - Rotate the paddings to portrait before applying - Don't use getOverviewActionsClaimedSpace() in fake landscape/seascape Bug: 344727200 Test: We can't currnetly autotest fake orientaiton Test: With gesture/3-button, rotate Overview to portriat/landscape/seascape/fake-landscape/fake-seascape, launch task and enter overview Flag: EXEMPT bugfix Change-Id: Icda0f483781921cae78f1ea3ef003562b60ad75a --- .../quickstep/BaseContainerInterface.java | 61 +++++++++++++------ .../orientation/LandscapePagedViewHandler.kt | 4 ++ .../orientation/PortraitPagedViewHandler.java | 5 ++ .../RecentsPagedOrientationHandler.kt | 3 + .../orientation/SeascapePagedViewHandler.kt | 4 ++ .../launcher3/util/DisplayController.java | 11 +++- 6 files changed, 69 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/quickstep/BaseContainerInterface.java b/quickstep/src/com/android/quickstep/BaseContainerInterface.java index 99551834f1..b1d511cfcd 100644 --- a/quickstep/src/com/android/quickstep/BaseContainerInterface.java +++ b/quickstep/src/com/android/quickstep/BaseContainerInterface.java @@ -41,7 +41,6 @@ import com.android.launcher3.R; import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.taskbar.TaskbarUIController; -import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.DisplayController; import com.android.launcher3.views.ScrimView; import com.android.quickstep.orientation.RecentsPagedOrientationHandler; @@ -207,10 +206,10 @@ public abstract class BaseContainerInterface

This method assumes that the animation is running so callers are expected to verify that + * before calling it. + */ + private float getExpandedBubbleTranslationXDuringScaleAnimation( + int bubbleIndex, int bubbleCount, boolean onLeft) { + // when the new bubble scale animation is running, a new bubble is animating in while the + // bubble bar is expanded, so we have at least 2 bubbles in the bubble bar - the expanded + // one, and the new one animating in. + + if (mNewBubbleScaleInAnimator == null) { + // callers of this method are expected to verify that the animation is running, but the + // compiler doesn't know that. + return 0; + } + final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing; + final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction(); + // the new bubble is scaling in from the center, so we need to adjust its translation so + // that the distance to the adjacent bubble scales at the same rate. + final float pivotAdjustment = -(1 - newBubbleScale) * mIconSize / 2f; + + if (onLeft) { + if (bubbleIndex == 0) { + // this is the animating bubble. use scaled spacing between it and the bubble to + // its left + return (bubbleCount - 1) * mIconSize + + (bubbleCount - 2) * mExpandedBarIconsSpacing + + newBubbleScale * mExpandedBarIconsSpacing + + pivotAdjustment; + } + // when the bubble bar is on the left, only the translation of the right-most bubble + // is affected by the scale animation. + return (bubbleCount - bubbleIndex - 1) * iconAndSpacing; + } else if (bubbleIndex == 0) { + // the bubble bar is on the right, and this is the animating bubble. it only needs + // to be adjusted for the scaling pivot. + return pivotAdjustment; + } else { + return iconAndSpacing * (bubbleIndex - 1 + newBubbleScale); } } @@ -804,7 +895,7 @@ public class BubbleBarView extends FrameLayout { addViewInLayout(child, i, child.getLayoutParams()); } } - updateChildrenRenderNodeProperties(mBubbleBarLocation); + updateBubblesLayoutProperties(mBubbleBarLocation); updateContentDescription(); } } @@ -883,15 +974,9 @@ public class BubbleBarView extends FrameLayout { private float arrowPositionForSelectedWhenExpanded(BubbleBarLocation bubbleBarLocation) { final int index = indexOfChild(mSelectedBubbleView); - final int bubblePosition; - if (bubbleBarLocation.isOnLeft(isLayoutRtl())) { - // Bubble positions are reversed. First bubble is on the right. - bubblePosition = getChildCount() - index - 1; - } else { - bubblePosition = index; - } - return getPaddingStart() + bubblePosition * (mIconSize + mExpandedBarIconsSpacing) - + mIconSize / 2f; + final float selectedBubbleTranslationX = getExpandedBubbleTranslationX( + index, getChildCount(), bubbleBarLocation.isOnLeft(isLayoutRtl())); + return getPaddingStart() + selectedBubbleTranslationX + mIconSize / 2f; } private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) { @@ -954,8 +1039,19 @@ public class BubbleBarView extends FrameLayout { final int childCount = getChildCount(); final int horizontalPadding = getPaddingStart() + getPaddingEnd(); // spaces amount is less than child count by 1, or 0 if no child views - int spacesCount = Math.max(childCount - 1, 0); - return childCount * mIconSize + spacesCount * mExpandedBarIconsSpacing + horizontalPadding; + final float totalSpace; + final float totalIconSize; + if (mNewBubbleScaleInAnimator != null && mNewBubbleScaleInAnimator.isRunning()) { + // when this animation is running, a new bubble is animating in while the bubble bar is + // expanded, so we have at least 2 bubbles in the bubble bar. + final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction(); + totalSpace = (childCount - 2 + newBubbleScale) * mExpandedBarIconsSpacing; + totalIconSize = (childCount - 1 + newBubbleScale) * mIconSize; + } else { + totalSpace = Math.max(childCount - 1, 0) * mExpandedBarIconsSpacing; + totalIconSize = childCount * mIconSize; + } + return totalIconSize + totalSpace + horizontalPadding; } private float collapsedWidth() { diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index 45a9fa16e3..0bfd1d7669 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -402,8 +402,8 @@ public class BubbleBarViewController { */ public void addBubble(BubbleBarItem b, boolean isExpanding, boolean suppressAnimation) { if (b != null) { - mBarView.addView(b.getView(), 0, - new FrameLayout.LayoutParams(mIconSize, mIconSize, Gravity.LEFT)); + mBarView.addBubble( + b.getView(), new FrameLayout.LayoutParams(mIconSize, mIconSize, Gravity.LEFT)); b.getView().setOnClickListener(mBubbleClickListener); mBubbleDragController.setupBubbleView(b.getView()); From 3fa291e1a7a8aae436276e30294c7cdcb833c6b0 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 7 Jun 2024 05:48:57 +0000 Subject: [PATCH 087/143] Add max width to the screen instructions view text - This ensures that the instruction wraps if the text is too long Fixes: 328577545 Fixes: 345128488 Flag: EXEMPT bugfix Test: Visual inspection of instructions view in different languages/form factors Change-Id: I73e889372a5c482277b0e4b61fb834304304c0a6 Merged-In: I73e889372a5c482277b0e4b61fb834304304c0a6 (cherry picked from commit 73cf3bc3a1b622275de7eca4b5b49710eff7aeaa) --- quickstep/res/layout/split_instructions_view.xml | 2 ++ quickstep/res/values-sw600dp/dimens.xml | 4 ++++ quickstep/res/values/dimens.xml | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/quickstep/res/layout/split_instructions_view.xml b/quickstep/res/layout/split_instructions_view.xml index 1115ff2b7c..797ea45be4 100644 --- a/quickstep/res/layout/split_instructions_view.xml +++ b/quickstep/res/layout/split_instructions_view.xml @@ -29,6 +29,7 @@ android:id="@+id/split_instructions_text" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:maxWidth="@dimen/split_instructions_view_max_width" android:textColor="?androidprv:attr/textColorOnAccent" android:text="@string/toast_split_select_app" /> @@ -36,6 +37,7 @@ android:id="@+id/split_instructions_text_cancel" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:layout_gravity="center_vertical" android:textColor="?androidprv:attr/textColorOnAccent" android:layout_marginStart="@dimen/split_instructions_start_margin_cancel" android:text="@string/toast_split_select_app_cancel" diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml index f9528b3632..e24d8fea79 100644 --- a/quickstep/res/values-sw600dp/dimens.xml +++ b/quickstep/res/values-sw600dp/dimens.xml @@ -45,4 +45,8 @@ 38sp 15sp + + + 300dp + diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index dbcba4904a..6a863f0fc8 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -464,4 +464,8 @@ 14sp 8dp + + + 220dp + From c1470021c86d49492f1eaa2d2e0390588f0fd98d Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Wed, 5 Jun 2024 18:19:55 -0700 Subject: [PATCH 088/143] Fix flaky test Attempts to fix a flaky test by ensuring that recents is always cleared before creating a split pair (so the split pair under test is always the same). Bug: 340935208 Test: testSaveAppPairMenuItemOrActionExistsOnSplitPair(), testSplitTaskTapBothIconMenus() Flag: TEST_ONLY Change-Id: Ibc81b90fac531f0e78e93a494ff59073ab5e52cf --- .../quickstep/views/OverviewActionsView.java | 2 +- .../quickstep/TaplOverviewIconTest.java | 2 ++ .../quickstep/TaplTestsSplitscreen.java | 18 +++----------- .../launcher3/ui/AbstractLauncherUiTest.java | 7 ++++++ .../android/launcher3/tapl/BaseOverview.java | 24 ++++++++++++++++--- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java index 604d072ad5..d9468c7038 100644 --- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java @@ -278,7 +278,7 @@ public class OverviewActionsView extends FrameLayo boolean showSingleTaskActions = !mIsGroupedTask; boolean showGroupActions = mIsGroupedTask && mDp.isTablet && mCanSaveAppPair; Log.d(TAG, "updateActionButtonsVisibility() called: showSingleTaskActions = [" - + showSingleTaskActions + ", showGroupActions = [" + showGroupActions + "]"); + + showSingleTaskActions + "], showGroupActions = [" + showGroupActions + "]"); getActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showSingleTaskActions ? 1 : 0); getGroupActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showGroupActions ? 1 : 0); } diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java index fa10b61ad4..b7fd8be311 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java @@ -88,6 +88,8 @@ public class TaplOverviewIconTest extends AbstractLauncherUiTest { UiDevice.getInstance(getInstrumentation()).pressHome(); mLauncher.waitForLauncherInitialized(); } + + /** Clears all recent tasks */ + protected void clearAllRecentTasks() { + if (!mLauncher.getRecentTasks().isEmpty()) { + mLauncher.goHome().switchToOverview().dismissAllTasks(); + } + } } diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index e10893eea5..567a8bd1c0 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -23,6 +23,7 @@ import static com.android.launcher3.tapl.OverviewTask.TASK_START_EVENT; import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL; import android.graphics.Rect; +import android.util.Log; import android.view.KeyEvent; import androidx.annotation.NonNull; @@ -44,6 +45,7 @@ import java.util.stream.Collectors; * Common overview panel for both Launcher and fallback recents */ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { + private static final String TAG = "BaseOverview"; protected static final String TASK_RES_ID = "task"; private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile( "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0"); @@ -384,25 +386,31 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { protected boolean isActionsViewVisible() { if (!hasTasks() || isClearAllVisible()) { + Log.d(TAG, "Not expecting an actions bar: no tasks/'Clear all' is visible"); return false; } boolean isTablet = mLauncher.isTablet(); if (isTablet && mLauncher.isGridOnlyOverviewEnabled()) { + Log.d(TAG, "Not expecting an actions bar: device is tablet with grid-only Overview"); return false; } OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask(); if (task == null) { + Log.d(TAG, "Not expecting an actions bar: no current task"); return false; } // In tablets, if focused task is not in center, overview actions aren't visible. if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) { + Log.d(TAG, "Not expecting an actions bar: device is tablet and task is not centered"); return false; } if (task.isTaskSplit() && (!mLauncher.isAppPairsEnabled() || !isTablet)) { + Log.d(TAG, "Not expecting an actions bar: device is phone and task is split"); // Overview actions aren't visible for split screen tasks, except for save app pair // button on tablets. return false; } + Log.d(TAG, "Expecting an actions bar"); return true; } @@ -447,10 +455,20 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { } private void verifyActionsViewVisibility() { + // If no running tasks, no need to verify actions view visibility. + if (getTasks().isEmpty()) { + return; + } + + boolean isTablet = mLauncher.isTablet(); + OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask(); + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( - "want to assert overview actions view visibility")) { - boolean isTablet = mLauncher.isTablet(); - OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask(); + "want to assert overview actions view visibility=" + + isActionsViewVisible() + + ", focused task is " + + (task == null ? "null" : (task.isTaskSplit() ? "split" : "not split")) + )) { if (isActionsViewVisible()) { if (task.isTaskSplit()) { From a2b510dc23b4e77b4d0fe3117f41c9b62a158e9a Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 21 May 2024 21:21:43 +0000 Subject: [PATCH 089/143] Move Desktop running apps support into TaskbarRecentAppsController - Merged DesktopTaskbarRunningAppsController up into TaskbarRecentAppsController, which is now initialized directly - The old TaskbarRecentAppsController was effectively a no-op that was always overridden, so merging the one subclass up makes things simpler (especially for the follow up CLs which will add support for switching between Running and Recent tasks using the same underlying data). Flag: com.android.launcher3.enable_recents_in_taskbar Test: TaskbarRecentAppsControllerTest Bug: 315354060 Change-Id: I8411fb832e5dd3d76201d2694dec0b11bd70bbf9 --- .../taskbar/TaskbarActivityContext.java | 16 +- .../launcher3/taskbar/TaskbarControllers.java | 5 +- .../taskbar/TaskbarModelCallbacks.java | 2 +- .../taskbar/TaskbarRecentAppsController.java | 77 --------- ...ller.kt => TaskbarRecentAppsController.kt} | 163 +++++++++--------- ....kt => TaskbarRecentAppsControllerTest.kt} | 50 +++--- 6 files changed, 116 insertions(+), 197 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java rename quickstep/src/com/android/launcher3/taskbar/{DesktopTaskbarRunningAppsController.kt => TaskbarRecentAppsController.kt} (62%) rename quickstep/tests/src/com/android/launcher3/taskbar/{DesktopTaskbarRunningAppsControllerTest.kt => TaskbarRecentAppsControllerTest.kt} (82%) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 0de0550016..61877f0afa 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -41,8 +41,6 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING; -import static com.android.window.flags.Flags.enableDesktopWindowingMode; -import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import static com.android.wm.shell.Flags.enableTinyTaskbar; import android.animation.AnimatorSet; @@ -304,7 +302,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new VoiceInteractionWindowController(this), new TaskbarTranslationController(this), new TaskbarSpringOnStashController(this), - createTaskbarRecentAppsController(), + new TaskbarRecentAppsController( + RecentsModel.INSTANCE.get(this), + LauncherActivityInterface.INSTANCE::getDesktopVisibilityController), TaskbarEduTooltipController.newInstance(this), new KeyboardQuickSwitchController(), new TaskbarPinningController(this, () -> @@ -314,16 +314,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mLauncherPrefs = LauncherPrefs.get(this); } - private TaskbarRecentAppsController createTaskbarRecentAppsController() { - // TODO(b/335401172): unify DesktopMode checks in Launcher - if (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) { - return new DesktopTaskbarRunningAppsController( - RecentsModel.INSTANCE.get(this), - LauncherActivityInterface.INSTANCE::getDesktopVisibilityController); - } - return TaskbarRecentAppsController.DEFAULT; - } - /** Updates {@link DeviceProfile} instances for any Taskbar windows. */ public void updateDeviceProfile(DeviceProfile launcherDp) { applyDeviceProfile(launcherDp); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index f9ddc3db2f..58c5e835c9 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -180,8 +180,9 @@ public class TaskbarControllers { taskbarUnfoldAnimationController, taskbarKeyguardController, stashedHandleViewController, taskbarStashController, taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController, - voiceInteractionWindowController, taskbarTranslationController, - taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController + voiceInteractionWindowController, taskbarRecentAppsController, + taskbarTranslationController, taskbarEduTooltipController, + keyboardQuickSwitchController, taskbarPinningController, }; mBackgroundRendererControllers = new BackgroundRendererController[] { taskbarDragLayerController, taskbarScrimViewController, diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java index 35e1c7baa9..2b0e1699cc 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java @@ -79,7 +79,7 @@ public class TaskbarModelCallbacks implements public void init(TaskbarControllers controllers) { mControllers = controllers; - if (mControllers.taskbarRecentAppsController.isEnabled()) { + if (mControllers.taskbarRecentAppsController.getCanShowRunningApps()) { RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this); if (shouldShowRunningAppsInDesktopMode()) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java deleted file mode 100644 index 606ba5b633..0000000000 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java +++ /dev/null @@ -1,77 +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.taskbar; - -import static java.util.Collections.emptySet; - -import androidx.annotation.CallSuper; -import androidx.annotation.NonNull; - -import com.android.launcher3.model.data.AppInfo; -import com.android.launcher3.model.data.ItemInfo; - -import java.util.Set; - -/** - * Base class for providing recent apps functionality - */ -public class TaskbarRecentAppsController { - - public static final TaskbarRecentAppsController DEFAULT = new TaskbarRecentAppsController(); - - // Initialized in init. - protected TaskbarControllers mControllers; - - @CallSuper - protected void init(TaskbarControllers taskbarControllers) { - mControllers = taskbarControllers; - } - - @CallSuper - protected void onDestroy() { - mControllers = null; - } - - /** Stores the current {@link AppInfo} instances, no-op except in desktop environment. */ - protected void setApps(AppInfo[] apps) { - } - - /** - * Indicates whether recent apps functionality is enabled, should return false except in - * desktop environment. - */ - protected boolean isEnabled() { - return false; - } - - /** Called to update hotseatItems, no-op except in desktop environment. */ - protected ItemInfo[] updateHotseatItemInfos(@NonNull ItemInfo[] hotseatItems) { - return hotseatItems; - } - - /** Called to update the list of currently running apps, no-op except in desktop environment. */ - protected void updateRunningApps() {} - - /** Returns the currently running apps, or an empty Set if outside of Desktop environment. */ - public Set getRunningApps() { - return emptySet(); - } - - /** Returns the set of apps whose tasks are all minimized. */ - public Set getMinimizedApps() { - return emptySet(); - } -} diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt similarity index 62% rename from quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt rename to quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt index d4bef28bf8..0946caf986 100644 --- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt @@ -13,37 +13,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.android.launcher3.taskbar import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration -import android.util.Log -import android.util.SparseArray import androidx.annotation.VisibleForTesting -import androidx.core.util.valueIterator +import com.android.launcher3.Flags.enableRecentsInTaskbar import com.android.launcher3.model.data.AppInfo import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.statehandlers.DesktopVisibilityController +import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController import com.android.quickstep.RecentsModel -import kotlin.collections.filterNotNull +import com.android.window.flags.Flags.enableDesktopWindowingMode +import com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps +import java.io.PrintWriter /** - * Shows running apps when in Desktop Mode. - * - * Users can enter and exit Desktop Mode at run-time, meaning this class falls back to the default - * recent-apps behaviour when outside of Desktop Mode. - * - * This class should only be used if - * [com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps] is enabled. + * Provides recent apps functionality, when the Taskbar Recent Apps section is enabled. Behavior: + * - When in Fullscreen mode: show the N most recent Tasks + * - When in Desktop Mode: show the currently running (open) Tasks */ -class DesktopTaskbarRunningAppsController( +class TaskbarRecentAppsController( private val recentsModel: RecentsModel, // Pass a provider here instead of the actual DesktopVisibilityController instance since that // instance might not be available when this constructor is called. private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?, -) : TaskbarRecentAppsController() { +) : LoggableTaskbarController { + + // TODO(b/335401172): unify DesktopMode checks in Launcher. + val canShowRunningApps = + enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps() + + // TODO(b/343532825): Add a setting to disable Recents even when the flag is on. + @VisibleForTesting + var isEnabled = enableRecentsInTaskbar() || canShowRunningApps + + // Initialized in init. + private lateinit var controllers: TaskbarControllers private var apps: Array? = null private var allRunningDesktopAppInfos: List? = null @@ -55,22 +62,40 @@ class DesktopTaskbarRunningAppsController( private val isInDesktopMode: Boolean get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false - override fun onDestroy() { - super.onDestroy() + val runningApps: Set + get() { + if (!isEnabled || !isInDesktopMode) { + return emptySet() + } + return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet() + } + + val minimizedApps: Set + get() { + if (!isInDesktopMode) { + return emptySet() + } + return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() + ?: emptySet() + } + + fun init(taskbarControllers: TaskbarControllers) { + controllers = taskbarControllers + } + + fun onDestroy() { apps = null } - @VisibleForTesting - public override fun setApps(apps: Array?) { + /** Stores the current [AppInfo] instances, no-op except in desktop environment. */ + fun setApps(apps: Array?) { this.apps = apps } - override fun isEnabled() = true - - @VisibleForTesting - public override fun updateHotseatItemInfos(hotseatItems: Array): Array { - if (!isInDesktopMode) { - Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode") + /** Called to update hotseatItems, in order to de-dupe them from Recent/Running tasks later. */ + // TODO(next CL): add new section of Tasks instead of changing Hotseat items + fun updateHotseatItemInfos(hotseatItems: Array): Array { + if (!isEnabled || !isInDesktopMode) { return hotseatItems } val newHotseatItemInfos = @@ -89,55 +114,6 @@ class DesktopTaskbarRunningAppsController( return newHotseatItemInfos.toTypedArray() } - override fun getRunningApps(): Set { - if (!isInDesktopMode) { - return emptySet() - } - return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet() - } - - override fun getMinimizedApps(): Set { - if (!isInDesktopMode) { - return emptySet() - } - return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet() - } - - @VisibleForTesting - public override fun updateRunningApps() { - if (!isInDesktopMode) { - Log.d(TAG, "updateRunningApps: not in Desktop Mode") - mControllers.taskbarViewController.commitRunningAppsToUI() - return - } - val runningTasks = getDesktopRunningTasks() - val runningAppInfo = getAppInfosFromRunningTasks(runningTasks) - allRunningDesktopAppInfos = runningAppInfo - updateMinimizedApps(runningTasks, runningAppInfo) - mControllers.taskbarViewController.commitRunningAppsToUI() - } - - private fun updateMinimizedApps( - runningTasks: List, - runningAppInfo: List, - ) { - val allRunningAppTasks = - runningAppInfo - .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } } - .associate { (appInfo, targetPackage) -> - appInfo to - runningTasks - .filter { it.realActivity?.packageName == targetPackage } - .map { it.taskId } - } - val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible } - allMinimizedDesktopAppInfos = - allRunningAppTasks - .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } } - .keys - .toList() - } - private fun getRunningDesktopAppInfosExceptHotseatApps( allRunningDesktopAppInfos: List, hotseatItems: List @@ -165,12 +141,43 @@ class DesktopTaskbarRunningAppsController( .filterNotNull() } - private fun getAppInfosFromRunningTask(task: RunningTaskInfo): AppInfo? = - apps?.firstOrNull { it.targetPackage == task.realActivity?.packageName } + /** Called to update the list of currently running apps, no-op except in desktop environment. */ + fun updateRunningApps() { + if (!isEnabled || !isInDesktopMode) { + return controllers.taskbarViewController.commitRunningAppsToUI() + } + val runningTasks = getDesktopRunningTasks() + val runningAppInfo = getAppInfosFromRunningTasks(runningTasks) + allRunningDesktopAppInfos = runningAppInfo + updateMinimizedApps(runningTasks, runningAppInfo) + controllers.taskbarViewController.commitRunningAppsToUI() + } - private fun SparseArray.toList(): List = valueIterator().asSequence().toList() + private fun updateMinimizedApps( + runningTasks: List, + runningAppInfo: List, + ) { + val allRunningAppTasks = + runningAppInfo + .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } } + .associate { (appInfo, targetPackage) -> + appInfo to + runningTasks + .filter { it.realActivity?.packageName == targetPackage } + .map { it.taskId } + } + val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible } + allMinimizedDesktopAppInfos = + allRunningAppTasks + .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } } + .keys + .toList() + } - companion object { - private const val TAG = "TabletDesktopTaskbarRunningAppsController" + override fun dumpLogs(prefix: String, pw: PrintWriter) { + pw.println("$prefix TaskbarRecentAppsController:") + pw.println("$prefix\tisEnabled=$isEnabled") + pw.println("$prefix\tcanShowRunningApps=$canShowRunningApps") + // TODO(next CL): add more logs } } diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt similarity index 82% rename from quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt rename to quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt index 5b567101b6..104263af5b 100644 --- a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt +++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt @@ -37,7 +37,7 @@ import org.mockito.junit.MockitoJUnit import org.mockito.kotlin.whenever @RunWith(AndroidTestingRunner::class) -class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { +class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() { @get:Rule val mockitoRule = MockitoJUnit.rule() @@ -46,19 +46,18 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { private var nextTaskId: Int = 500 - private lateinit var taskbarRunningAppsController: DesktopTaskbarRunningAppsController + private lateinit var recentAppsController: TaskbarRecentAppsController private lateinit var userHandle: UserHandle @Before fun setUp() { super.setup() userHandle = Process.myUserHandle() - taskbarRunningAppsController = - DesktopTaskbarRunningAppsController(mockRecentsModel) { - mockDesktopVisibilityController - } - taskbarRunningAppsController.init(taskbarControllers) - taskbarRunningAppsController.setApps( + recentAppsController = + TaskbarRecentAppsController(mockRecentsModel) { mockDesktopVisibilityController } + recentAppsController.init(taskbarControllers) + recentAppsController.isEnabled = true + recentAppsController.setApps( ALL_APP_PACKAGES.map { createTestAppInfo(packageName = it) }.toTypedArray() ) } @@ -69,7 +68,7 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { val hotseatItems = createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2)) - assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())) + assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())) .isEqualTo(hotseatItems.toTypedArray()) } @@ -81,10 +80,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { val runningTasks = createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)) whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks) - taskbarRunningAppsController.updateRunningApps() + recentAppsController.updateRunningApps() val newHotseatItems = - taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()) + recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()) assertThat(newHotseatItems.map { it?.targetPackage }) .containsExactlyElementsIn(hotseatPackages) @@ -96,7 +95,7 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { val hotseatItems = createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2)) - assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())) + assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())) .isEqualTo(hotseatItems.toTypedArray()) } @@ -108,10 +107,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { val runningTasks = createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)) whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks) - taskbarRunningAppsController.updateRunningApps() + recentAppsController.updateRunningApps() val newHotseatItems = - taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()) + recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()) val expectedPackages = listOf( @@ -134,10 +133,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { listOf(HOTSEAT_PACKAGE_1, RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2) ) whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks) - taskbarRunningAppsController.updateRunningApps() + recentAppsController.updateRunningApps() val newHotseatItems = - taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()) + recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()) val expectedPackages = listOf( @@ -156,10 +155,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { val runningTasks = createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)) whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks) - taskbarRunningAppsController.updateRunningApps() + recentAppsController.updateRunningApps() - assertThat(taskbarRunningAppsController.runningApps).isEmpty() - assertThat(taskbarRunningAppsController.minimizedApps).isEmpty() + assertThat(recentAppsController.runningApps).isEmpty() + assertThat(recentAppsController.minimizedApps).isEmpty() } @Test @@ -168,11 +167,11 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { val runningTasks = createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)) whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks) - taskbarRunningAppsController.updateRunningApps() + recentAppsController.updateRunningApps() - assertThat(taskbarRunningAppsController.runningApps) + assertThat(recentAppsController.runningApps) .containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2) - assertThat(taskbarRunningAppsController.minimizedApps).isEmpty() + assertThat(recentAppsController.minimizedApps).isEmpty() } @Test @@ -187,12 +186,11 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() { ) ) whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks) - taskbarRunningAppsController.updateRunningApps() + recentAppsController.updateRunningApps() - assertThat(taskbarRunningAppsController.runningApps) + assertThat(recentAppsController.runningApps) .containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2, RUNNING_APP_PACKAGE_3) - assertThat(taskbarRunningAppsController.minimizedApps) - .containsExactly(RUNNING_APP_PACKAGE_3) + assertThat(recentAppsController.minimizedApps).containsExactly(RUNNING_APP_PACKAGE_3) } private fun createHotseatItemsFromPackageNames(packageNames: List): List { From e94e5094131246f878a524da4aa3f4fb101570f0 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Mon, 10 Jun 2024 19:40:43 -0700 Subject: [PATCH 090/143] Expand touch target of split cancel button to meet a11y requirements This CL adds a TouchDelegate to the "Cancel" button on SplitInstructionsView so that it is always at least 48dp by 48dp. I.e. if the touch target is smaller than 48dp, it expands the TouchDelegate to be at least that size. Fixes: 323108127 Test: Manually verified that the touch target is larger Flag: EXEMPT bugfix Change-Id: Id14bc39660ee7767991a3b5613f1282945a2ef96 --- .../views/SplitInstructionsView.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java index a56d51e515..3d994e89a8 100644 --- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java +++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java @@ -18,13 +18,16 @@ package com.android.quickstep.views; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_CANCEL_BUTTON; +import static com.android.settingslib.widget.theme.R.dimen.settingslib_preferred_minimum_touch_target; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.content.Context; +import android.graphics.Rect; import android.util.AttributeSet; import android.util.FloatProperty; +import android.view.TouchDelegate; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; @@ -41,9 +44,7 @@ import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StateManager; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.states.StateAnimationConfig; - import com.android.quickstep.util.SplitSelectStateController; /** @@ -133,6 +134,28 @@ public class SplitInstructionsView extends LinearLayout { cancelTextView.setVisibility(VISIBLE); cancelTextView.setOnClickListener((v) -> exitSplitSelection()); instructionTextView.setText(R.string.toast_contextual_split_select_app); + + // After layout, expand touch target of cancel button to meet minimum a11y measurements. + post(() -> { + int minTouchSize = getResources() + .getDimensionPixelSize(settingslib_preferred_minimum_touch_target); + Rect r = new Rect(); + cancelTextView.getHitRect(r); + + if (r.width() < minTouchSize) { + // add 1 to ensure ceiling on int division + int expandAmount = (minTouchSize + 1 - r.width()) / 2; + r.left -= expandAmount; + r.right += expandAmount; + } + if (r.height() < minTouchSize) { + int expandAmount = (minTouchSize + 1 - r.height()) / 2; + r.top -= expandAmount; + r.bottom += expandAmount; + } + + setTouchDelegate(new TouchDelegate(r, cancelTextView)); + }); } // Set accessibility title, will be announced by a11y tools. From 9e12c3f152eda5993408cad32e73ff9bed80d7f4 Mon Sep 17 00:00:00 2001 From: Charlie Anderson Date: Mon, 10 Jun 2024 18:31:01 -0400 Subject: [PATCH 091/143] Adding bugfix flag for archiving bug extras Bug: 322314760 Test: locally Flag: com.android.launcher3.enable_first_screen_broadcast_archiving_extras Change-Id: I33edcf09eee990727613246fb5942263feb49625 --- aconfig/launcher.aconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig index 22fe82b0ec..fecc43d0b2 100644 --- a/aconfig/launcher.aconfig +++ b/aconfig/launcher.aconfig @@ -291,3 +291,14 @@ flag { description: "Replace hybrid hotseat app predictions with strictly Recent Apps" bug: "315354060" } + +flag { + name: "enable_first_screen_broadcast_archiving_extras" + namespace: "launcher" + description: "adds Extras to first screen broadcast for archived apps" + bug: "322314760" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} From 2eff95ef6d13496ed1f3b28ab42898ba738882c4 Mon Sep 17 00:00:00 2001 From: Michal Brzezinski Date: Mon, 10 Jun 2024 14:23:36 +0100 Subject: [PATCH 092/143] Disabling touchpad gestures in launcher for SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED state As gestures start with checking of canStartTrackpadGesture() method, disabling it there disables all touchpad gestures. Test: RecentsAnimationDeviceStateTest Flag: NONE these changes are not directly flagged but usage of SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED state is guarded by flag: com.android.systemui.new_touchpad_gestures_tutorial Bug: 345207568 Change-Id: I0409475a3e006609c6b722cd3b17d75e1ebed939 --- .../RecentsAnimationDeviceState.java | 29 ++++-- .../RecentsAnimationDeviceStateTest.kt | 98 ++++++++++++++++++- 2 files changed, 116 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 8bcdaa380f..7adce74f8c 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -45,6 +45,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_Q import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED; import android.app.ActivityTaskManager; import android.content.Context; @@ -386,7 +387,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E boolean canStartWithNavHidden = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0 || (mSystemUiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0 || mRotationTouchHelper.isTaskListFrozen(); - return canStartWithNavHidden && canStartTrackpadGesture(); + return canStartWithNavHidden && canStartAnyGesture(); } /** @@ -395,14 +396,24 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E * mode. */ public boolean canStartTrackpadGesture() { - return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0 - && (mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0 - && (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0 - && (mSystemUiStateFlags & SYSUI_STATE_MAGNIFICATION_OVERLAP) == 0 - && ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 - || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0) - && (mSystemUiStateFlags & SYSUI_STATE_DEVICE_DREAMING) == 0 - && (mSystemUiStateFlags & SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION) == 0; + boolean trackpadGesturesEnabled = + (mSystemUiStateFlags & SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED) == 0; + return trackpadGesturesEnabled && canStartAnyGesture(); + } + + /** + * Common logic to determine if either trackpad or finger gesture can be started + */ + private boolean canStartAnyGesture() { + boolean homeOrOverviewEnabled = (mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 + || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0; + long gestureDisablingStates = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED + | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING + | SYSUI_STATE_QUICK_SETTINGS_EXPANDED + | SYSUI_STATE_MAGNIFICATION_OVERLAP + | SYSUI_STATE_DEVICE_DREAMING + | SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION; + return (gestureDisablingStates & mSystemUiStateFlags) == 0 && homeOrOverviewEnabled; } /** diff --git a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt index 5157c71471..80fbce7265 100644 --- a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt +++ b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt @@ -9,8 +9,19 @@ import com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE import com.android.launcher3.util.DisplayController.CHANGE_ROTATION import com.android.launcher3.util.DisplayController.Info import com.android.launcher3.util.NavigationMode -import com.android.launcher3.util.window.WindowManagerProxy import com.android.quickstep.util.GestureExclusionManager +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED +import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -28,7 +39,6 @@ import org.mockito.kotlin.whenever class RecentsAnimationDeviceStateTest { @Mock private lateinit var exclusionManager: GestureExclusionManager - @Mock private lateinit var windowManagerProxy: WindowManagerProxy @Mock private lateinit var info: Info private val context = ApplicationProvider.getApplicationContext() as Context @@ -108,4 +118,88 @@ class RecentsAnimationDeviceStateTest { verifyZeroInteractions(exclusionManager) } + + @Test + fun trackpadGesturesNotAllowedForSelectedStates() { + val disablingStates = GESTURE_DISABLING_SYSUI_STATES + + SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED + + allSysUiStates().forEach { state -> + val canStartGesture = !disablingStates.contains(state) + underTest.setSystemUiFlags(state) + assertThat(underTest.canStartTrackpadGesture()).isEqualTo(canStartGesture) + } + } + + @Test + fun trackpadGesturesNotAllowedIfHomeAndOverviewIsDisabled() { + val stateToExpectedResult = mapOf( + SYSUI_STATE_HOME_DISABLED to true, + SYSUI_STATE_OVERVIEW_DISABLED to true, + DEFAULT_STATE + .enable(SYSUI_STATE_OVERVIEW_DISABLED) + .enable(SYSUI_STATE_HOME_DISABLED) to false + ) + + stateToExpectedResult.forEach { (state, allowed) -> + underTest.setSystemUiFlags(state) + assertThat(underTest.canStartTrackpadGesture()).isEqualTo(allowed) + } + } + + @Test + fun systemGesturesNotAllowedForSelectedStates() { + val disablingStates = GESTURE_DISABLING_SYSUI_STATES + SYSUI_STATE_NAV_BAR_HIDDEN + + allSysUiStates().forEach { state -> + val canStartGesture = !disablingStates.contains(state) + underTest.setSystemUiFlags(state) + assertThat(underTest.canStartSystemGesture()).isEqualTo(canStartGesture) + } + } + + @Test + fun systemGesturesNotAllowedWhenGestureStateDisabledAndNavBarVisible() { + val stateToExpectedResult = mapOf( + DEFAULT_STATE + .enable(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) + .disable(SYSUI_STATE_NAV_BAR_HIDDEN) to true, + DEFAULT_STATE + .enable(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) + .enable(SYSUI_STATE_NAV_BAR_HIDDEN) to true, + DEFAULT_STATE + .disable(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) + .disable(SYSUI_STATE_NAV_BAR_HIDDEN) to true, + DEFAULT_STATE + .disable(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) + .enable(SYSUI_STATE_NAV_BAR_HIDDEN) to false, + ) + + stateToExpectedResult.forEach {(state, gestureAllowed) -> + underTest.setSystemUiFlags(state) + assertThat(underTest.canStartSystemGesture()).isEqualTo(gestureAllowed) + } + } + + private fun allSysUiStates(): List { + // SYSUI_STATES_* are binary flags + return (0..SYSUI_STATES_COUNT).map { 1L shl it } + } + + companion object { + private val GESTURE_DISABLING_SYSUI_STATES = listOf( + SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED, + SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING, + SYSUI_STATE_QUICK_SETTINGS_EXPANDED, + SYSUI_STATE_MAGNIFICATION_OVERLAP, + SYSUI_STATE_DEVICE_DREAMING, + SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION, + ) + private const val SYSUI_STATES_COUNT = 33 + private const val DEFAULT_STATE = 0L + } + + private fun Long.enable(state: Long) = this or state + + private fun Long.disable(state: Long) = this and state.inv() } From 31a65a08dc3ec38ace426af91185a3b9ff59a106 Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Mon, 10 Jun 2024 13:08:15 -0700 Subject: [PATCH 093/143] Fix Taskbar All Apps Button to be Fixed in Minimal Taskbar State Test: Manual Bug: 346387672 Flag: NONE taskbar all apps is not behind a flag Change-Id: Iea63ccf57354a1e2941bd51f7f6f9e69187c4545 --- .../android/launcher3/taskbar/TaskbarViewController.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 23495adcf7..55745b557a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -347,6 +347,11 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar float allAppIconTranslateRange = mapRange(scale, transientTaskbarAllAppsOffset, persistentTaskbarAllAppsOffset); + // no x translation required when all apps button is the only icon in taskbar. + if (iconViews.length <= 1) { + allAppIconTranslateRange = 0f; + } + if (mIsRtl) { allAppIconTranslateRange *= -1; } @@ -377,7 +382,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar -finalMarginScale * (iconIndex - halfIconCount)); } - if (iconView.equals(mTaskbarView.getAllAppsButtonView()) && iconViews.length > 1) { + if (iconView.equals(mTaskbarView.getAllAppsButtonView())) { ((IconButtonView) iconView).setTranslationXForTaskbarAllAppsIcon( allAppIconTranslateRange); } From 1deac6777b169dce21745a1e407ec9956cf3e4cc Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 11 Jun 2024 10:40:17 -0700 Subject: [PATCH 094/143] Fix crash from isTrackpadDevice Apparently InputManager.getInputDevice can return null when a device is added Fixes: 344902395 Test: N/A Change-Id: I79c3dd3431b1d4b079b8a6863688a13ea2741602 --- .../src/com/android/quickstep/TouchInteractionService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 58bb8fc7c4..e10b56de69 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -512,6 +512,9 @@ public class TouchInteractionService extends Service { private boolean isTrackpadDevice(int deviceId) { InputDevice inputDevice = mInputManager.getInputDevice(deviceId); + if (inputDevice == null) { + return false; + } return inputDevice.getSources() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHPAD); } From 84f9cfabb9a71b776717cb14ff6c7c5bad16dfb6 Mon Sep 17 00:00:00 2001 From: mpodolian Date: Tue, 11 Jun 2024 01:15:20 +0100 Subject: [PATCH 095/143] Add outline to the bubble bar background view. Added outline to the bubble bar background. Updated pointer appearing/disappearing animation - now pointer moves into the bubble bar background. Demo: http://recall/-/gx8ASgewUeUS3QYohfrd1J/e1wZMrFZTILq73ik8wwrwx Fixes: 345489039 Flag: ACONFIG com.android.wm.shell.enable_bubble_bar DEVELOPMENT Test: Manual. Expand and collapse bubble bar with the light and the dark theme. Change-Id: I095fdc12337955aa21ee0eb622a924ad424ef186 --- quickstep/res/values/dimens.xml | 1 + .../taskbar/bubbles/BubbleBarBackground.kt | 150 +++++++++++------- .../taskbar/bubbles/BubbleBarView.java | 5 +- res/color-night-v31/taskbar_stroke.xml | 19 +++ res/color/taskbar_stroke.xml | 19 +++ .../launcher3/popup/RoundedArrowDrawable.java | 5 +- 6 files changed, 135 insertions(+), 64 deletions(-) create mode 100644 res/color-night-v31/taskbar_stroke.xml create mode 100644 res/color/taskbar_stroke.xml diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 7f09b6e8ed..c1acaa0219 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -364,6 +364,7 @@ 150dp 24dp 40dp + 1dp 10dp 32dp 8dp diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt index a59e81b68e..bc13c89855 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt @@ -19,7 +19,9 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.ColorFilter +import android.graphics.Matrix import android.graphics.Paint +import android.graphics.Path import android.graphics.PixelFormat import android.graphics.drawable.Drawable import com.android.app.animation.Interpolators @@ -28,28 +30,28 @@ import com.android.launcher3.Utilities import com.android.launcher3.Utilities.mapToRange import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound import com.android.launcher3.popup.RoundedArrowDrawable +import kotlin.math.max +import kotlin.math.min /** Drawable for the background of the bubble bar. */ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) : Drawable() { - private val DARK_THEME_SHADOW_ALPHA = 51f - private val LIGHT_THEME_SHADOW_ALPHA = 25f - - private val paint: Paint = Paint() - private val pointerWidth: Float - private val pointerHeight: Float - private val pointerTipRadius: Float - private val pointerVisibleHeight: Float + private val fillPaint: Paint = Paint() + private val strokePaint: Paint = Paint() + private val arrowWidth: Float + private val arrowHeight: Float + private val arrowTipRadius: Float + private val arrowVisibleHeight: Float private val shadowAlpha: Float private var shadowBlur = 0f private var keyShadowDistance = 0f + private var arrowHeightFraction = 1f var arrowPositionX: Float = 0f private set private var showingArrow: Boolean = false - private var arrowDrawable: RoundedArrowDrawable var width: Float = 0f @@ -70,34 +72,31 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) } init { - paint.color = context.getColor(R.color.taskbar_background) - paint.flags = Paint.ANTI_ALIAS_FLAG - paint.style = Paint.Style.FILL - val res = context.resources + // configure fill paint + fillPaint.color = context.getColor(R.color.taskbar_background) + fillPaint.flags = Paint.ANTI_ALIAS_FLAG + fillPaint.style = Paint.Style.FILL + // configure stroke paint + strokePaint.color = context.getColor(R.color.taskbar_stroke) + strokePaint.flags = Paint.ANTI_ALIAS_FLAG + strokePaint.style = Paint.Style.STROKE + strokePaint.strokeWidth = res.getDimension(R.dimen.transient_taskbar_stroke_width) + // apply theme alpha attributes + if (Utilities.isDarkTheme(context)) { + strokePaint.alpha = DARK_THEME_STROKE_ALPHA + shadowAlpha = DARK_THEME_SHADOW_ALPHA + } else { + strokePaint.alpha = LIGHT_THEME_STROKE_ALPHA + shadowAlpha = LIGHT_THEME_SHADOW_ALPHA + } + shadowBlur = res.getDimension(R.dimen.transient_taskbar_shadow_blur) keyShadowDistance = res.getDimension(R.dimen.transient_taskbar_key_shadow_distance) - pointerWidth = res.getDimension(R.dimen.bubblebar_pointer_width) - pointerHeight = res.getDimension(R.dimen.bubblebar_pointer_height) - pointerVisibleHeight = res.getDimension(R.dimen.bubblebar_pointer_visible_size) - pointerTipRadius = res.getDimension(R.dimen.bubblebar_pointer_radius) - - shadowAlpha = - if (Utilities.isDarkTheme(context)) { - DARK_THEME_SHADOW_ALPHA - } else { - LIGHT_THEME_SHADOW_ALPHA - } - - arrowDrawable = - RoundedArrowDrawable.createVerticalRoundedArrow( - pointerWidth, - pointerHeight, - pointerTipRadius, - /* isPointingUp= */ true, - context.getColor(R.color.taskbar_background) - ) - arrowDrawable.setBounds(0, 0, pointerWidth.toInt(), pointerHeight.toInt()) + arrowWidth = res.getDimension(R.dimen.bubblebar_pointer_width) + arrowHeight = res.getDimension(R.dimen.bubblebar_pointer_height) + arrowVisibleHeight = res.getDimension(R.dimen.bubblebar_pointer_visible_size) + arrowTipRadius = res.getDimension(R.dimen.bubblebar_pointer_radius) } fun showArrow(show: Boolean) { @@ -115,40 +114,53 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) // TODO (b/277359345): Should animate the alpha similar to taskbar (see TaskbarDragLayer) // Draw shadows. val newShadowAlpha = - mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, shadowAlpha, Interpolators.LINEAR) - paint.setShadowLayer( + mapToRange(fillPaint.alpha.toFloat(), 0f, 255f, 0f, shadowAlpha, Interpolators.LINEAR) + fillPaint.setShadowLayer( shadowBlur, 0f, keyShadowDistance, setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha)) ) - arrowDrawable.setShadowLayer( - shadowBlur, - 0f, - keyShadowDistance, - setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha)) - ) - - // Draw background. + // Create background path + val backgroundPath = Path() val radius = backgroundHeight / 2f val left = bounds.left + (if (anchorLeft) 0f else bounds.width().toFloat() - width) val right = bounds.left + (if (anchorLeft) width else bounds.width().toFloat()) - val top = bounds.top + pointerVisibleHeight + val top = bounds.top + arrowVisibleHeight val bottom = bounds.top + bounds.height().toFloat() - canvas.drawRoundRect(left, top, right, bottom, radius, radius, paint) + backgroundPath.addRoundRect(left, top, right, bottom, radius, radius, Path.Direction.CW) + addArrowPathIfNeeded(backgroundPath) - if (showingArrow) { - // Draw arrow. - val transX = bounds.left + arrowPositionX - pointerWidth / 2f - canvas.translate(transX, 0f) - arrowDrawable.draw(canvas) - } + // Draw background. + canvas.drawPath(backgroundPath, fillPaint) + canvas.drawPath(backgroundPath, strokePaint) canvas.restore() } + private fun addArrowPathIfNeeded(sourcePath: Path) { + if (!showingArrow || arrowHeightFraction <= 0) return + val arrowPath = Path() + RoundedArrowDrawable.addDownPointingRoundedTriangleToPath( + arrowWidth, + arrowHeight, + arrowTipRadius, + arrowPath + ) + // flip it horizontally + val pathTransform = Matrix() + pathTransform.setRotate(180f, arrowWidth * 0.5f, arrowHeight * 0.5f) + arrowPath.transform(pathTransform) + // shift to arrow position + val arrowStart = bounds.left + arrowPositionX - (arrowWidth / 2f) + val arrowTop = (1 - arrowHeightFraction) * arrowVisibleHeight + arrowPath.offset(arrowStart, arrowTop) + // union with rectangle + sourcePath.op(arrowPath, Path.Op.UNION) + } + override fun getOpacity(): Int { - return when (paint.alpha) { + return when (fillPaint.alpha) { 255 -> PixelFormat.OPAQUE 0 -> PixelFormat.TRANSPARENT else -> PixelFormat.TRANSLUCENT @@ -156,24 +168,40 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) } override fun setAlpha(alpha: Int) { - paint.alpha = alpha - arrowDrawable.alpha = alpha + fillPaint.alpha = alpha invalidateSelf() } override fun getAlpha(): Int { - return paint.alpha + return fillPaint.alpha } override fun setColorFilter(colorFilter: ColorFilter?) { - paint.colorFilter = colorFilter - } - - fun setArrowAlpha(alpha: Int) { - arrowDrawable.alpha = alpha + fillPaint.colorFilter = colorFilter } fun setHeight(newHeight: Float) { backgroundHeight = newHeight } + + /** + * Set fraction of the arrow height that should be displayed. Allowed values range are [0..1]. + * If value passed is out of range it will be converted to the closest value in tha allowed + * range. + */ + fun setArrowHeightFraction(arrowHeightFraction: Float) { + var newHeightFraction = arrowHeightFraction + if (newHeightFraction !in 0f..1f) { + newHeightFraction = min(max(newHeightFraction, 0f), 1f) + } + this.arrowHeightFraction = newHeightFraction + invalidateSelf() + } + + companion object { + private const val DARK_THEME_STROKE_ALPHA = 51 + private const val LIGHT_THEME_STROKE_ALPHA = 41 + private const val DARK_THEME_SHADOW_ALPHA = 51f + private const val LIGHT_THEME_SHADOW_ALPHA = 25f + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index f3ac1e44ba..5f9a7527b6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -729,7 +729,7 @@ public class BubbleBarView extends FrameLayout { } } mBubbleBarBackground.setArrowPosition(arrowPosition); - mBubbleBarBackground.setArrowAlpha((int) (255 * widthState)); + mBubbleBarBackground.setArrowHeightFraction(widthState); mBubbleBarBackground.setWidth(interpolatedWidth); } @@ -882,7 +882,8 @@ public class BubbleBarView extends FrameLayout { // bubbles than the current bubble and overflow. bubblePosition = index == 0 && getChildCount() > MAX_VISIBLE_BUBBLES_COLLAPSED ? 1 : 0; } else { - bubblePosition = index; + bubblePosition = index >= MAX_VISIBLE_BUBBLES_COLLAPSED + ? MAX_VISIBLE_BUBBLES_COLLAPSED - 1 : index; } return getPaddingStart() + bubblePosition * (mIconOverlapAmount) + mIconSize / 2f; } diff --git a/res/color-night-v31/taskbar_stroke.xml b/res/color-night-v31/taskbar_stroke.xml new file mode 100644 index 0000000000..db7a510620 --- /dev/null +++ b/res/color-night-v31/taskbar_stroke.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/res/color/taskbar_stroke.xml b/res/color/taskbar_stroke.xml new file mode 100644 index 0000000000..b691082c98 --- /dev/null +++ b/res/color/taskbar_stroke.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/src/com/android/launcher3/popup/RoundedArrowDrawable.java b/src/com/android/launcher3/popup/RoundedArrowDrawable.java index 575052ccc5..2610bd67c3 100644 --- a/src/com/android/launcher3/popup/RoundedArrowDrawable.java +++ b/src/com/android/launcher3/popup/RoundedArrowDrawable.java @@ -175,7 +175,10 @@ public class RoundedArrowDrawable extends Drawable { mPaint.setShadowLayer(shadowBlur, dx, dy, shadowColor); } - private static void addDownPointingRoundedTriangleToPath(float width, float height, + /** + * Adds rounded triangle pointing down to the provided {@link Path path} argument + */ + public static void addDownPointingRoundedTriangleToPath(float width, float height, float radius, Path path) { // Calculated for the arrow pointing down, will be flipped later if needed. From 261a62219b4526c9c7be03992a14ea540a712b65 Mon Sep 17 00:00:00 2001 From: Himanshu Gupta Date: Fri, 31 May 2024 12:35:09 +0100 Subject: [PATCH 096/143] Prompting the user to set Pixel/Quickstep as default Home app. requestQuietMode API throws SecurityException in case its called from a non-default Launcher app. To mitigate this, we catch the exception and prompt the user to set their default launcher to the current app. Video(Pixel): https://photos.app.goo.gl/ni5X1c6vBbYW2JMJ9 Video(Pixel-aosp): https://photos.app.goo.gl/cYLJpTYW76Jnbonc9 Bug: 320446272 Test: Manual Flag: NONE Bug fix tweak. Change-Id: I6afb2ae85cabc038e1503e9c34eebd974c4f7a50 --- .../launcher3/uioverrides/SystemApiWrapper.kt | 57 ++++++++++++++++++- res/values/strings.xml | 2 + src/com/android/launcher3/Launcher.java | 13 +++++ .../android/launcher3/LauncherConstants.java | 1 + .../allapps/PrivateProfileManager.java | 20 ++++++- .../launcher3/allapps/UserProfileManager.java | 7 +-- .../android/launcher3/util/ApiWrapper.java | 20 +++++++ 7 files changed, 113 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt index 146ff3da50..04696364e0 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt +++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt @@ -17,24 +17,32 @@ package com.android.launcher3.uioverrides import android.app.ActivityOptions import android.app.PendingIntent +import android.app.role.RoleManager import android.content.Context +import android.content.IIntentReceiver +import android.content.IIntentSender 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.Bundle import android.os.Flags.allowPrivateProfile +import android.os.IBinder import android.os.UserHandle import android.os.UserManager import android.util.ArrayMap +import android.widget.Toast 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.R import com.android.launcher3.Utilities import com.android.launcher3.proxy.ProxyActivityStarter import com.android.launcher3.util.ApiWrapper +import com.android.launcher3.util.Executors import com.android.launcher3.util.StartActivityParams import com.android.launcher3.util.UserIconInfo import com.android.quickstep.util.FadeOutRemoteTransition @@ -115,8 +123,7 @@ open class SystemApiWrapper(context: Context?) : ApiWrapper(context) { intentSender = mContext .getSystemService(LauncherApps::class.java) - ?.privateSpaceSettingsIntent - ?: return null + ?.privateSpaceSettingsIntent ?: return null options = ActivityOptions.makeBasic() .setPendingIntentBackgroundActivityStartMode( @@ -130,4 +137,50 @@ open class SystemApiWrapper(context: Context?) : ApiWrapper(context) { override fun isNonResizeableActivity(lai: LauncherActivityInfo) = lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE + + /** + * Starts an Activity which can be used to set this Launcher as the HOME app, via a consent + * screen. In case the consent screen cannot be shown, or the user does not set current Launcher + * as HOME app, a toast asking the user to do the latter is shown. + */ + override fun assignDefaultHomeRole(context: Context) { + val roleManager = context.getSystemService(RoleManager::class.java) + if ( + (roleManager!!.isRoleAvailable(RoleManager.ROLE_HOME) && + !roleManager.isRoleHeld(RoleManager.ROLE_HOME)) + ) { + val roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME) + val pendingIntent = + PendingIntent( + object : IIntentSender.Stub() { + override fun send( + code: Int, + intent: Intent, + resolvedType: String?, + allowlistToken: IBinder?, + finishedReceiver: IIntentReceiver?, + requiredPermission: String?, + options: Bundle? + ) { + if (code != -1) { + Executors.MAIN_EXECUTOR.execute { + Toast.makeText( + context, + context.getString( + R.string.set_default_home_app, + context.getString(R.string.derived_app_name) + ), + Toast.LENGTH_LONG + ) + .show() + } + } + } + } + ) + val params = StartActivityParams(pendingIntent, 0) + params.intent = roleRequestIntent + context.startActivity(ProxyActivityStarter.getLaunchIntent(context, params)) + } + } } diff --git a/res/values/strings.xml b/res/values/strings.xml index a9cca6de41..d33adc41f3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -36,6 +36,8 @@ Shortcut isn\'t available Home + + Set %1$s as default home app in Settings diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2b30dc404f..02a2939c49 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -38,6 +38,7 @@ import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_BIND import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_BIND_PENDING_APPWIDGET; import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_CREATE_APPWIDGET; import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_CREATE_SHORTCUT; +import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_HOME_ROLE; import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_PICK_APPWIDGET; import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_RECONFIGURE_APPWIDGET; import static com.android.launcher3.LauncherConstants.SavedInstanceKeys.RUNTIME_STATE; @@ -151,6 +152,7 @@ import android.view.WindowInsetsAnimation; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.animation.OvershootInterpolator; +import android.widget.Toast; import android.window.BackEvent; import android.window.OnBackAnimationCallback; @@ -891,6 +893,17 @@ public class Launcher extends StatefulActivity } mPendingActivityResult = null; + if (requestCode == REQUEST_HOME_ROLE) { + if (resultCode != RESULT_OK) { + Toast.makeText( + this, + this.getString(R.string.set_default_home_app, + this.getString(R.string.derived_app_name)), + Toast.LENGTH_LONG).show(); + } + return; + } + // Reset the startActivity waiting flag final PendingRequestArgs requestArgs = mPendingRequestArgs; setWaitingForResult(null); diff --git a/src/com/android/launcher3/LauncherConstants.java b/src/com/android/launcher3/LauncherConstants.java index 1abfeb902f..445fb4134c 100644 --- a/src/com/android/launcher3/LauncherConstants.java +++ b/src/com/android/launcher3/LauncherConstants.java @@ -41,6 +41,7 @@ public class LauncherConstants { public static final int REQUEST_BIND_PENDING_APPWIDGET = 12; public static final int REQUEST_RECONFIGURE_APPWIDGET = 13; + public static final int REQUEST_HOME_ROLE = 14; static final int REQUEST_CREATE_SHORTCUT = 1; static final int REQUEST_CREATE_APPWIDGET = 5; static final int REQUEST_PICK_APPWIDGET = 9; diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index 5cacf60615..6f021eacf7 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -281,10 +281,28 @@ public class PrivateProfileManager extends UserProfileManager { @Override public void setQuietMode(boolean enable) { - super.setQuietMode(enable); + UI_HELPER_EXECUTOR.post(() -> + mUserCache.getUserProfiles() + .stream() + .filter(getUserMatcher()) + .findFirst() + .ifPresent(userHandle -> setQuietModeSafely(enable, userHandle))); mReadyToAnimate = true; } + /** + * Sets Quiet Mode for Private Profile. + * If {@link SecurityException} is thrown, prompts the user to set this launcher as HOME app. + */ + private void setQuietModeSafely(boolean enable, UserHandle userHandle) { + try { + mUserManager.requestQuietModeEnabled(enable, userHandle); + } catch (SecurityException ex) { + ApiWrapper.INSTANCE.get(mAllApps.mActivityContext) + .assignDefaultHomeRole(mAllApps.mActivityContext); + } + } + /** * Expand the private space after the app list has been added and updated from * {@link AlphabeticalAppsList#onAppsUpdated()} diff --git a/src/com/android/launcher3/allapps/UserProfileManager.java b/src/com/android/launcher3/allapps/UserProfileManager.java index eb74d20fae..93b6b29b34 100644 --- a/src/com/android/launcher3/allapps/UserProfileManager.java +++ b/src/com/android/launcher3/allapps/UserProfileManager.java @@ -55,12 +55,11 @@ public abstract class UserProfileManager { public @interface UserProfileState { } protected final StatsLogManager mStatsLogManager; + protected final UserManager mUserManager; + protected final UserCache mUserCache; + @UserProfileState private int mCurrentState; - - private final UserManager mUserManager; - private final UserCache mUserCache; - protected UserProfileManager(UserManager userManager, StatsLogManager statsLogManager, UserCache userCache) { diff --git a/src/com/android/launcher3/util/ApiWrapper.java b/src/com/android/launcher3/util/ApiWrapper.java index 6429a437bf..095518c8ea 100644 --- a/src/com/android/launcher3/util/ApiWrapper.java +++ b/src/com/android/launcher3/util/ApiWrapper.java @@ -16,10 +16,12 @@ package com.android.launcher3.util; +import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_HOME_ROLE; import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; import android.app.ActivityOptions; import android.app.Person; +import android.app.role.RoleManager; import android.content.Context; import android.content.Intent; import android.content.pm.LauncherActivityInfo; @@ -33,6 +35,7 @@ import android.util.ArrayMap; import androidx.annotation.Nullable; import com.android.launcher3.BuildConfig; +import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -136,6 +139,23 @@ public class ApiWrapper implements ResourceBasedOverride, SafeCloseable { return false; } + /** + * Starts an Activity which can be used to set this Launcher as the HOME app, via a consent + * screen. In case the consent screen cannot be shown, or the user does not set current Launcher + * as HOME app, a toast asking the user to do the latter is shown. + */ + public void assignDefaultHomeRole(Context context) { + RoleManager roleManager = context.getSystemService(RoleManager.class); + assert roleManager != null; + if (roleManager.isRoleAvailable(RoleManager.ROLE_HOME) + && !roleManager.isRoleHeld(RoleManager.ROLE_HOME)) { + Intent roleRequestIntent = roleManager.createRequestRoleIntent( + RoleManager.ROLE_HOME); + Launcher launcher = Launcher.getLauncher(context); + launcher.startActivityForResult(roleRequestIntent, REQUEST_HOME_ROLE); + } + } + @Override public void close() { } From 3a4b79bf7b838a74918484d4fbcab58420d6da3c Mon Sep 17 00:00:00 2001 From: Himanshu Gupta Date: Fri, 7 Jun 2024 18:29:42 +0100 Subject: [PATCH 097/143] Scrolling down to locate PS after lock/unlock event. This change fixes TAPL tests by: 1. Scrolling down to locate PS, in case the scrollbar moves after lock/unlock. 2. Retrying lock/unlock, as sometimes, the request is cancelled by UserManager (if the profile is already in that state) Bug: 345556016 Test: atest TaplPrivateSpaceTest Flag: NONE Tapl fix tweak. Change-Id: Ic0cc3259a2f92065a699d694c47f65c5f68934b8 --- .../quickstep/TaplPrivateSpaceTest.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java index 82905085fe..23a29f7840 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java @@ -35,7 +35,6 @@ import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.rule.ScreenRecordRule; import org.junit.After; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,6 +49,7 @@ public class TaplPrivateSpaceTest extends AbstractQuickStepTest { private static final String PRIVATE_PROFILE_NAME = "LauncherPrivateProfile"; private static final String INSTALLED_APP_NAME = "Aardwolf"; + private static final int MAX_STATE_TOGGLE_TRIES = 2; private static final String TAG = "TaplPrivateSpaceTest"; @Override @@ -167,14 +167,15 @@ public class TaplPrivateSpaceTest extends AbstractQuickStepTest { @Test @ScreenRecordRule.ScreenRecord // b/334946529 - @Ignore("b/339179262") public void testPrivateSpaceLockingBehaviour() throws IOException { // Scroll to the bottom of All Apps executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader()); HomeAllApps homeAllApps = mLauncher.getAllApps(); // Disable Private Space - togglePrivateSpace(PrivateProfileManager.STATE_DISABLED, homeAllApps); + togglePrivateSpaceWithRetry(PrivateProfileManager.STATE_DISABLED, homeAllApps); + // Scroll to the bottom of All Apps + executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader()); homeAllApps.freeze(); try { @@ -186,7 +187,9 @@ public class TaplPrivateSpaceTest extends AbstractQuickStepTest { } // Enable Private Space - togglePrivateSpace(PrivateProfileManager.STATE_ENABLED, homeAllApps); + togglePrivateSpaceWithRetry(PrivateProfileManager.STATE_ENABLED, homeAllApps); + // Scroll to the bottom of All Apps + executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader()); homeAllApps.freeze(); try { @@ -219,6 +222,25 @@ public class TaplPrivateSpaceTest extends AbstractQuickStepTest { waitForLauncherUIUpdate(); } + private void togglePrivateSpaceWithRetry(int state, HomeAllApps homeAllApps) { + int togglePsCount = 0; + boolean shouldRetry; + do { + togglePsCount ++; + try { + togglePrivateSpace(state, homeAllApps); + // No need to retry if the toggle was successful. + shouldRetry = false; + } catch (AssertionError error) { + if (togglePsCount < MAX_STATE_TOGGLE_TRIES) { + shouldRetry = true; + } else { + throw error; + } + } + } while (shouldRetry); + } + private void waitForPrivateSpaceSetup() { waitForLauncherCondition("Private Profile not setup", launcher -> launcher.getAppsView().hasPrivateProfile(), From 3eb4efac95571eb5837ca66cae840033fc5fd893 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Tue, 11 Jun 2024 15:52:55 -0400 Subject: [PATCH 098/143] Exclude home and recents activity types when overriding recents-excluded tasks These tasks could point to overview itself, causing a very confusing screenshot. By excluding these tasks, we will default to using the task preview Flag: NONE bug fix Fixes: 336334715 Test: used circle to search from home, swiped to home, then pressed "select" overview action button. also checked temp logs Change-Id: I0b0ca50585413b479e4830f06b57b8b5e19670a8 --- quickstep/src/com/android/quickstep/TopTaskTracker.java | 6 ++++-- .../src/com/android/quickstep/TouchInteractionService.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java index 3a6b8042cd..8ffb84edec 100644 --- a/quickstep/src/com/android/quickstep/TopTaskTracker.java +++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java @@ -242,7 +242,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub * If the given task holds an activity that is excluded from recents, and there * is another running task that is not excluded from recents, returns that underlying task. */ - public @Nullable CachedTaskInfo otherVisibleTaskThisIsExcludedOver() { + public @Nullable CachedTaskInfo getVisibleNonExcludedTask() { if (mTopTask == null || (mTopTask.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) { // Not an excluded task. @@ -250,7 +250,9 @@ public class TopTaskTracker extends ISplitScreenListener.Stub } List visibleNonExcludedTasks = mAllCachedTasks.stream() .filter(t -> t.isVisible - && (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) + && (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0 + && t.getActivityType() != ACTIVITY_TYPE_HOME + && t.getActivityType() != ACTIVITY_TYPE_RECENTS) .toList(); return visibleNonExcludedTasks.isEmpty() ? null : new CachedTaskInfo(visibleNonExcludedTasks); diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 4599f180b1..b66a6dee40 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -1174,7 +1174,7 @@ public class TouchInteractionService extends Service { // running activity as the task behind the overlay. TopTaskTracker.CachedTaskInfo otherVisibleTask = runningTask == null ? null - : runningTask.otherVisibleTaskThisIsExcludedOver(); + : runningTask.getVisibleNonExcludedTask(); if (otherVisibleTask != null) { ActiveGestureLog.INSTANCE.addLog(new CompoundString("Changing active task to ") .append(otherVisibleTask.getPackageName()) From 70041c88ad314b88b80e892ff0ab0a0273c56002 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 11 Jun 2024 13:06:03 -0700 Subject: [PATCH 099/143] Initialize mRotationTouchHelper before onInputDeviceAdded There is dependency there that can cause npe from mRotationTouchHelper not initialized yet Fixes: 345893434 Test: N/A Change-Id: Ib9009f23d71eccf6b554e21c51ba640304250af0 --- .../src/com/android/quickstep/TouchInteractionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 58bb8fc7c4..fe42f8c319 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -578,6 +578,7 @@ public class TouchInteractionService extends Service { mMainChoreographer = Choreographer.getInstance(); mAM = ActivityManagerWrapper.getInstance(); mDeviceState = new RecentsAnimationDeviceState(this, true); + mRotationTouchHelper = mDeviceState.getRotationTouchHelper(); mAllAppsActionManager = new AllAppsActionManager( this, UI_HELPER_EXECUTOR, this::createAllAppsPendingIntent); mInputManager = getSystemService(InputManager.class); @@ -590,7 +591,6 @@ public class TouchInteractionService extends Service { } } mTaskbarManager = new TaskbarManager(this, mAllAppsActionManager, mNavCallbacks); - mRotationTouchHelper = mDeviceState.getRotationTouchHelper(); mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); // Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized. From c948537a826d6ea1ca90698105fb654f24691119 Mon Sep 17 00:00:00 2001 From: Orhan Uysal Date: Wed, 5 Jun 2024 13:58:02 +0000 Subject: [PATCH 100/143] Use RecentTasksListener to trigger TopTaskTracker Currently launcher gets task stack updates through WM core. Ideally we would like to migrate into a model where launcher gets these updates through shell instead. Test: Manually check that the correct task info is delivered to launcher from shell Bug: 341932484 Bug: 344684650 Flag: NONE Just adding a listener, no logic added Change-Id: Iaf534a4bfee968138d4a4ff282a66e62759af2c0 --- .../src/com/android/quickstep/RecentTasksList.java | 13 ++++++++++--- .../src/com/android/quickstep/RecentsModel.java | 3 ++- .../src/com/android/quickstep/TopTaskTracker.java | 6 +++--- .../com/android/quickstep/RecentTasksListTest.java | 4 +++- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java index 37b4dcabb8..b08a46f3c2 100644 --- a/quickstep/src/com/android/quickstep/RecentTasksList.java +++ b/quickstep/src/com/android/quickstep/RecentTasksList.java @@ -75,7 +75,7 @@ public class RecentTasksList { private ArrayList mRunningTasks; public RecentTasksList(LooperExecutor mainThreadExecutor, KeyguardManager keyguardManager, - SystemUiProxy sysUiProxy) { + SystemUiProxy sysUiProxy, TopTaskTracker topTaskTracker) { mMainThreadExecutor = mainThreadExecutor; mKeyguardManager = keyguardManager; mChangeId = 1; @@ -106,6 +106,13 @@ public class RecentTasksList { RecentTasksList.this.onRunningTaskChanged(taskInfo); }); } + + @Override + public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) { + mMainThreadExecutor.execute(() -> { + topTaskTracker.onTaskMovedToFront(taskInfo); + }); + } }); // We may receive onRunningTaskAppeared events later for tasks which have already been // included in the list returned by mSysUiProxy.getRunningTasks(), or may receive @@ -135,7 +142,7 @@ public class RecentTasksList { * Asynchronously fetches the list of recent tasks, reusing cached list if available. * * @param loadKeysOnly Whether to load other associated task data, or just the key - * @param callback The callback to receive the list of recent tasks + * @param callback The callback to receive the list of recent tasks * @return The change id of the current task list */ public synchronized int getTasks(boolean loadKeysOnly, @@ -200,7 +207,7 @@ public class RecentTasksList { mChangeId++; } - /** + /** * Registers a listener for running tasks */ public void registerRunningTasksListener(RecentsModel.RunningTasksListener listener) { diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index 98c1eb409c..6eefe4aee5 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -90,7 +90,8 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener, this(context, new RecentTasksList(MAIN_EXECUTOR, context.getSystemService(KeyguardManager.class), - SystemUiProxy.INSTANCE.get(context)), + SystemUiProxy.INSTANCE.get(context), + TopTaskTracker.INSTANCE.get(context)), new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider), new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR), iconProvider, diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java index 29c80fd066..61ba56477d 100644 --- a/quickstep/src/com/android/quickstep/TopTaskTracker.java +++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java @@ -64,7 +64,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskStackChangeListener, SafeCloseable { private static final String TAG = "TopTaskTracker"; - + private static final boolean DEBUG = true; public static MainThreadInitializedObject INSTANCE = @@ -204,7 +204,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub /** * @return index 0 will be task in left/top position, index 1 in right/bottom position. - * Will return empty array if device is not in staged split + * Will return empty array if device is not in staged split */ public int[] getRunningSplitTaskIds() { if (mMainStagePosition.taskId == INVALID_TASK_ID @@ -337,7 +337,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub */ public Task[] getPlaceholderTasks() { return mTopTask == null ? new Task[0] - : new Task[] {Task.from(new TaskKey(mTopTask), mTopTask, false)}; + : new Task[]{Task.from(new TaskKey(mTopTask), mTopTask, false)}; } /** diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java index ed5526f410..03244eb0bf 100644 --- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java +++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java @@ -48,6 +48,8 @@ public class RecentTasksListTest { @Mock private SystemUiProxy mockSystemUiProxy; + @Mock + private TopTaskTracker mTopTaskTracker; // Class under test private RecentTasksList mRecentTasksList; @@ -58,7 +60,7 @@ public class RecentTasksListTest { LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class); KeyguardManager mockKeyguardManager = mock(KeyguardManager.class); mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManager, - mockSystemUiProxy); + mockSystemUiProxy, mTopTaskTracker); } @Test From f9c602d1d9cdcff0faafe20ab04ee6ccbe69c627 Mon Sep 17 00:00:00 2001 From: Saumya Prakash Date: Fri, 17 May 2024 23:30:17 +0000 Subject: [PATCH 101/143] Change Pinned taskbar corners to be fixed. Based on new UX guidelines, the corners for the pinned taskbar should be 16 dp. Fix: 337872323 Test: Put device in 3 button mode and pinned taskbar and observe sharper, fixed corners. Transient taskbar remains unchanged. Flag: EXEMPT bugfix Change-Id: I2130e91dcdc0afb007fde93438f3fa603bc15af8 --- .../taskbar/TaskbarActivityContext.java | 23 +++---------- .../taskbar/TaskbarBackgroundRenderer.kt | 33 ++++++++----------- .../com/android/quickstep/views/TaskView.kt | 17 +++++++++- res/values/dimens.xml | 3 ++ 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 1571ac0ea5..b757842c3e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -63,7 +63,6 @@ import android.provider.Settings; import android.util.Log; import android.view.Display; import android.view.Gravity; -import android.view.RoundedCorner; import android.view.Surface; import android.view.View; import android.view.WindowInsets; @@ -167,7 +166,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { private final TaskbarControllers mControllers; private final WindowManager mWindowManager; - private final @Nullable RoundedCorner mLeftCorner, mRightCorner; private DeviceProfile mDeviceProfile; private WindowManager.LayoutParams mWindowLayoutParams; private boolean mIsFullscreen; @@ -228,16 +226,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { Context c = getApplicationContext(); mWindowManager = c.getSystemService(WindowManager.class); - boolean phoneMode = isPhoneMode(); - mLeftCorner = phoneMode - ? null - : display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT); - mRightCorner = phoneMode - ? null - : display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT); - // Inflate views. - int taskbarLayout = DisplayController.isTransientTaskbar(this) && !phoneMode + int taskbarLayout = DisplayController.isTransientTaskbar(this) && !isPhoneMode() ? R.layout.transient_taskbar : R.layout.taskbar; mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(taskbarLayout, null, false); @@ -617,12 +607,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mImeDrawsImeNavBar; } - public int getLeftCornerRadius() { - return mLeftCorner == null ? 0 : mLeftCorner.getRadius(); - } - - public int getRightCornerRadius() { - return mRightCorner == null ? 0 : mRightCorner.getRadius(); + public int getCornerRadius() { + return isPhoneMode() ? 0 : getResources().getDimensionPixelSize( + R.dimen.persistent_taskbar_corner_radius); } public WindowManager.LayoutParams getWindowLayoutParams() { @@ -1015,7 +1002,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mDeviceProfile.taskbarHeight - + Math.max(getLeftCornerRadius(), getRightCornerRadius()) + + getCornerRadius() + extraHeightForTaskbarTooltips; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt index e290c3fa3d..16ff665bfc 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt @@ -66,15 +66,13 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { private var keyShadowDistance = 0f private var bottomMargin = 0 - private val fullLeftCornerRadius = context.leftCornerRadius.toFloat() - private val fullRightCornerRadius = context.rightCornerRadius.toFloat() - private var leftCornerRadius = fullLeftCornerRadius - private var rightCornerRadius = fullRightCornerRadius + private val fullCornerRadius = context.cornerRadius.toFloat() + private var cornerRadius = fullCornerRadius private var widthInsetPercentage = 0f - private val square: Path = Path() - private val circle: Path = Path() - private val invertedLeftCornerPath: Path = Path() - private val invertedRightCornerPath: Path = Path() + private val square = Path() + private val circle = Path() + private val invertedLeftCornerPath = Path() + private val invertedRightCornerPath = Path() private var stashedHandleWidth = context.resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width) @@ -103,7 +101,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { } /** - * Sets the roundness of the round corner above Taskbar. No effect on transient Taskkbar. + * Sets the roundness of the round corner above Taskbar. No effect on transient Taskbar. * * @param cornerRoundness 0 has no round corner, 1 has complete round corner. */ @@ -112,21 +110,18 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { return } - leftCornerRadius = fullLeftCornerRadius * cornerRoundness - rightCornerRadius = fullRightCornerRadius * cornerRoundness + cornerRadius = fullCornerRadius * cornerRoundness // Create the paths for the inverted rounded corners above the taskbar. Start with a filled // square, and then subtract out a circle from the appropriate corner. square.reset() - square.addRect(0f, 0f, leftCornerRadius, leftCornerRadius, Path.Direction.CW) + square.addRect(0f, 0f, cornerRadius, cornerRadius, Path.Direction.CW) circle.reset() - circle.addCircle(leftCornerRadius, 0f, leftCornerRadius, Path.Direction.CW) + circle.addCircle(cornerRadius, 0f, cornerRadius, Path.Direction.CW) invertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE) - square.reset() - square.addRect(0f, 0f, rightCornerRadius, rightCornerRadius, Path.Direction.CW) circle.reset() - circle.addCircle(0f, 0f, rightCornerRadius, Path.Direction.CW) + circle.addCircle(0f, 0f, cornerRadius, Path.Direction.CW) invertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE) } @@ -160,10 +155,10 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { } // Draw the inverted rounded corners above the taskbar. - canvas.translate(0f, -leftCornerRadius) + canvas.translate(0f, -cornerRadius) canvas.drawPath(invertedLeftCornerPath, paint) - canvas.translate(0f, leftCornerRadius) - canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius) + canvas.translate(0f, cornerRadius) + canvas.translate(canvas.width - cornerRadius, -cornerRadius) canvas.drawPath(invertedRightCornerPath, paint) } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index 05b9d40a7e..a38f8a08af 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -63,6 +63,7 @@ import com.android.launcher3.pm.UserCache import com.android.launcher3.testing.TestLogging import com.android.launcher3.testing.shared.TestProtocol import com.android.launcher3.util.CancellableTask +import com.android.launcher3.util.DisplayController import com.android.launcher3.util.Executors import com.android.launcher3.util.RunnableList import com.android.launcher3.util.SafeCloseable @@ -75,6 +76,7 @@ import com.android.launcher3.util.TraceHelper import com.android.launcher3.util.TransformingTouchDelegate import com.android.launcher3.util.ViewPool import com.android.launcher3.util.rects.set +import com.android.launcher3.views.ActivityContext import com.android.quickstep.RecentsModel import com.android.quickstep.RemoteAnimationTargets import com.android.quickstep.TaskAnimationManager @@ -1521,7 +1523,20 @@ constructor( @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) open fun computeWindowCornerRadius(context: Context): Float { - return QuickStepContract.getWindowCornerRadius(context) + val activityContext: ActivityContext? = ActivityContext.lookupContextNoThrow(context) + + // The corner radius is fixed to match when Taskbar is persistent mode + return if ( + activityContext != null && + activityContext.deviceProfile?.isTaskbarPresent == true && + DisplayController.isTransientTaskbar(context) + ) { + context.resources + .getDimensionPixelSize(R.dimen.persistent_taskbar_corner_radius) + .toFloat() + } else { + QuickStepContract.getWindowCornerRadius(context) + } } /** Sets the progress in range [0, 1] */ diff --git a/res/values/dimens.xml b/res/values/dimens.xml index e31a35ff6f..68641f38ad 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -443,6 +443,9 @@ 16dp + + 16dp + 1dp From eecadb0432d29518513a815143422c2bac30cd69 Mon Sep 17 00:00:00 2001 From: Uwais Ashraf Date: Tue, 11 Jun 2024 22:05:31 +0000 Subject: [PATCH 102/143] Enable UtilitiesKtTest for multivalent. Remove test resource Fix: 325088427 Test: UtilitiesKtTest in studio and presubmit Flag: EXEMPT test-only Change-Id: I71b77c4633b1075f643ed479f8224f9b80811f54 --- .../com/android/launcher3/UtilitiesKtTest.kt | 23 ++++--------- tests/res/layout/utilities_test_view.xml | 33 ------------------- 2 files changed, 7 insertions(+), 49 deletions(-) rename tests/{ => multivalentTests}/src/com/android/launcher3/UtilitiesKtTest.kt (87%) delete mode 100644 tests/res/layout/utilities_test_view.xml diff --git a/tests/src/com/android/launcher3/UtilitiesKtTest.kt b/tests/multivalentTests/src/com/android/launcher3/UtilitiesKtTest.kt similarity index 87% rename from tests/src/com/android/launcher3/UtilitiesKtTest.kt rename to tests/multivalentTests/src/com/android/launcher3/UtilitiesKtTest.kt index 9aa0369d51..0d13e7722d 100644 --- a/tests/src/com/android/launcher3/UtilitiesKtTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/UtilitiesKtTest.kt @@ -17,9 +17,8 @@ package com.android.launcher3 import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry @@ -27,28 +26,20 @@ import com.android.launcher3.UtilitiesKt.CLIP_CHILDREN_FALSE_MODIFIER import com.android.launcher3.UtilitiesKt.CLIP_TO_PADDING_FALSE_MODIFIER import com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree import com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree -import com.android.launcher3.tests.R import com.google.common.truth.Truth.assertThat -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class UtilitiesKtTest { - val context: Context = InstrumentationRegistry.getInstrumentation().context - private lateinit var rootView: ViewGroup - private lateinit var midView: ViewGroup - private lateinit var childView: View - @Before - fun setup() { - rootView = - LayoutInflater.from(context).inflate(R.layout.utilities_test_view, null) as ViewGroup - midView = rootView.requireViewById(R.id.mid_view) - childView = rootView.requireViewById(R.id.child_view) - } + private val childView = TextView(context) + + private val midView = LinearLayout(context).apply { addView(childView) } + + private val rootView = LinearLayout(context).apply { addView(midView) } @Test fun set_clipChildren_false() { diff --git a/tests/res/layout/utilities_test_view.xml b/tests/res/layout/utilities_test_view.xml deleted file mode 100644 index dc2a51573a..0000000000 --- a/tests/res/layout/utilities_test_view.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - \ No newline at end of file From 4a4b7a80592896055727d25416b3f23092a43625 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 11 Jun 2024 14:17:20 -0700 Subject: [PATCH 103/143] Delay taskbar background fade in animation - Taskbar background will fade in based on 1. Velocity threshold 2. End target gesture destination Bug: 298089923 Bug: 345768019 Test: swipe up fast to go home, note no taskbar bg swipe up slow to reveal taskhome, note taskbar bg shows immediately Flag: com.android.launcher3.enable_scaling_reveal_home_animation DISABLED Change-Id: I2c16352e1c0c52a8afc49900a39b80383bacde62 --- quickstep/res/values/dimens.xml | 5 ++ .../taskbar/TaskbarActivityContext.java | 7 ++ .../launcher3/taskbar/TaskbarDragLayer.java | 7 +- .../taskbar/TaskbarStashController.java | 77 ++++++++++++++++++- .../taskbar/TaskbarUIController.java | 7 ++ .../android/quickstep/AbsSwipeUpHandler.java | 12 +++ .../TaskbarUnstashInputConsumer.java | 47 +++++++++++ 7 files changed, 158 insertions(+), 4 deletions(-) diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 08d36d8d87..44eb6a591d 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -384,6 +384,11 @@ 24dp + + + -288dp + 80 + 4.5 10 diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 0de0550016..487d9aad6b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -1405,6 +1405,13 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mControllers.taskbarStashController.toggleTaskbarStash(); } + /** + * Plays the taskbar background alpha animation if one is not currently playing. + */ + public void playTaskbarBackgroundAlphaAnimation() { + mControllers.taskbarStashController.playTaskbarBackgroundAlphaAnimation(); + } + /** * Called to start the taskbar translation spring to its settled translation (0). */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index 84874a9371..f703463117 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -18,6 +18,7 @@ package com.android.launcher3.taskbar; import static android.view.KeyEvent.ACTION_UP; import static android.view.KeyEvent.KEYCODE_BACK; +import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION; import android.content.Context; @@ -41,6 +42,7 @@ import com.android.app.viewcapture.ViewCaptureFactory; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.MultiPropertyFactory; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.views.BaseDragLayer; @@ -104,7 +106,10 @@ public class TaskbarDragLayer extends BaseDragLayer { mTaskbarBackgroundAlpha = new MultiPropertyFactory<>(this, BG_ALPHA, INDEX_COUNT, (a, b) -> a * b, 1f); mTaskbarBackgroundAlpha.get(INDEX_ALL_OTHER_STATES).setValue(0); - mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM).setValue(1); + mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM).setValue( + enableScalingRevealHomeAnimation() && DisplayController.isTransientTaskbar(context) + ? 0 + : 1); } public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 74d2d60014..a9521aea72 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -22,6 +22,7 @@ import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; import static com.android.internal.jank.InteractionJankMonitor.Configuration; +import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW; @@ -40,6 +41,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_S import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; +import android.animation.ValueAnimator; import android.app.RemoteAction; import android.graphics.drawable.Icon; import android.os.SystemClock; @@ -239,6 +241,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private final Alarm mTimeoutAlarm = new Alarm(); private boolean mEnableBlockingTimeoutDuringTests = false; + private Animator mTaskbarBackgroundAlphaAnimator; + private long mTaskbarBackgroundDuration; + private boolean mIsGoingHome; + // Evaluate whether the handle should be stashed private final LongPredicate mIsStashedPredicate = flags -> { boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP); @@ -258,6 +264,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity); mAccessibilityManager = mActivity.getSystemService(AccessibilityManager.class); + mTaskbarBackgroundDuration = + activity.getResources().getInteger(R.integer.taskbar_background_duration); if (mActivity.isPhoneMode()) { mUnstashedHeight = mActivity.getResources().getDimensionPixelSize( R.dimen.taskbar_phone_size); @@ -752,9 +760,16 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba backgroundAndHandleAlphaStartDelay, backgroundAndHandleAlphaDuration, LINEAR); - play(as, mTaskbarBackgroundAlphaForStash.animateToValue(backgroundAlphaTarget), - backgroundAndHandleAlphaStartDelay, - backgroundAndHandleAlphaDuration, LINEAR); + if (enableScalingRevealHomeAnimation() && !isStashed) { + play(as, getTaskbarBackgroundAnimatorWhenNotGoingHome(duration), + 0, 0, LINEAR); + as.addListener(AnimatorListeners.forEndCallback( + () -> mTaskbarBackgroundAlphaForStash.setValue(backgroundAlphaTarget))); + } else { + play(as, mTaskbarBackgroundAlphaForStash.animateToValue(backgroundAlphaTarget), + backgroundAndHandleAlphaStartDelay, + backgroundAndHandleAlphaDuration, LINEAR); + } // The rest of the animations might be "skipped" in TRANSITION_HANDLE_FADE transitions. AnimatorSet skippable = as; @@ -797,6 +812,62 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba .setDuration(isStashed ? duration / 2 : duration)); } + private Animator getTaskbarBackgroundAnimatorWhenNotGoingHome(long duration) { + ValueAnimator a = ValueAnimator.ofFloat(0, 1); + a.setDuration(duration); + a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + // This value is arbitrary. + private static final float ANIMATED_FRACTION_THRESHOLD = 0.25f; + private boolean mTaskbarBgAlphaAnimationStarted = false; + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + if (mIsGoingHome) { + mTaskbarBgAlphaAnimationStarted = true; + } + if (mTaskbarBgAlphaAnimationStarted) { + return; + } + + if (valueAnimator.getAnimatedFraction() >= ANIMATED_FRACTION_THRESHOLD) { + if (!mIsGoingHome) { + playTaskbarBackgroundAlphaAnimation(); + setUserIsGoingHome(false); + mTaskbarBgAlphaAnimationStarted = true; + } + } + } + }); + return a; + } + + /** + * Sets whether the user is going home based on the current gesture. + */ + public void setUserIsGoingHome(boolean isGoingHome) { + mIsGoingHome = isGoingHome; + } + + /** + * Plays the taskbar background alpha animation if one is not currently playing. + */ + public void playTaskbarBackgroundAlphaAnimation() { + if (mTaskbarBackgroundAlphaAnimator != null + && mTaskbarBackgroundAlphaAnimator.isRunning()) { + return; + } + mTaskbarBackgroundAlphaAnimator = mTaskbarBackgroundAlphaForStash + .animateToValue(1f) + .setDuration(mTaskbarBackgroundDuration); + mTaskbarBackgroundAlphaAnimator.setInterpolator(LINEAR); + mTaskbarBackgroundAlphaAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mTaskbarBackgroundAlphaAnimator = null; + } + }); + mTaskbarBackgroundAlphaAnimator.start(); + } + private static void play(AnimatorSet as, @Nullable Animator a, long startDelay, long duration, Interpolator interpolator) { if (a == null) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index 2b68b52932..593285f062 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -411,4 +411,11 @@ public class TaskbarUIController { public void setSkipNextRecentsAnimEnd() { // Overridden } + + /** + * Sets whether the user is going home based on the current gesture. + */ + public void setUserIsGoingHome(boolean isGoingHome) { + mControllers.taskbarStashController.setUserIsGoingHome(isGoingHome); + } } diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 463222dfd0..5903a27bfa 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -32,6 +32,7 @@ import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.Flags.enableAdditionalHomeAnimations; import static com.android.launcher3.Flags.enableGridOnlyOverview; +import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; import static com.android.launcher3.PagedView.INVALID_PAGE; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE; @@ -1193,6 +1194,10 @@ public abstract class AbsSwipeUpHandler= NUM_MOTION_MOVE_THRESHOLD // Arbitrary value + && velocityYPxPerS != 0 // Ignore these + && velocityYPxPerS >= mTaskbarSlowVelocityYThreshold) { + mTaskbarActivityContext.playTaskbarBackgroundAlphaAnimation(); + mCanPlayTaskbarBgAlphaAnimation = false; + } + } + private void cleanupAfterMotionEvent() { mTaskbarActivityContext.setAutohideSuspendFlag( FLAG_AUTOHIDE_SUSPEND_TOUCHING, false); @@ -264,6 +304,13 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { mIsInBubbleBarArea = false; mIsVerticalGestureOverBubbleBar = false; mIsPassedBubbleBarSlop = false; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + } + mVelocityTracker = null; + mCanPlayTaskbarBgAlphaAnimation = true; + mMotionMoveCount = 0; } private boolean isInBubbleBarArea(float x) { From cfafb55331f233de58cd5b3c1c132199023e2a9d Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Mon, 10 Jun 2024 15:30:51 -0700 Subject: [PATCH 104/143] Convert ENABLE_FLOATING_SEARCH_BAR to aconfig. Flag: com.android.launcher3.floating_search_bar Test: Build (existing code unchanged) Bug: 346408388 Fix: 346406981 Change-Id: Ia8d15ceb1b2b4754657844d602cb95b9555a4ece --- aconfig/launcher.aconfig | 7 +++++++ src/com/android/launcher3/DeviceProfile.java | 3 +-- src/com/android/launcher3/config/FeatureFlags.java | 5 ----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig index fecc43d0b2..9c945b9b35 100644 --- a/aconfig/launcher.aconfig +++ b/aconfig/launcher.aconfig @@ -302,3 +302,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "floating_search_bar" + namespace: "launcher" + description: "Search bar persists at the bottom of the screen across Launcher states" + bug: "346408388" +} diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 0daabb1451..00db3a3886 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -53,7 +53,6 @@ import androidx.core.content.res.ResourcesCompat; import com.android.launcher3.CellLayout.ContainerType; import com.android.launcher3.DevicePaddings.DevicePadding; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.icons.IconNormalizer; import com.android.launcher3.model.data.ItemInfo; @@ -714,7 +713,7 @@ public class DeviceProfile { overviewTaskThumbnailTopMarginPx = enableOverviewIconMenu() ? 0 : overviewTaskIconSizePx + overviewTaskMarginPx; // Don't add margin with floating search bar to minimize risk of overlapping. - overviewActionsTopMarginPx = FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() ? 0 + overviewActionsTopMarginPx = Flags.floatingSearchBar() ? 0 : res.getDimensionPixelSize(R.dimen.overview_actions_top_margin); overviewPageSpacing = res.getDimensionPixelSize(R.dimen.overview_page_spacing); overviewActionsButtonSpacing = res.getDimensionPixelSize( diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 4b908bfb12..33e6f9106f 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -84,11 +84,6 @@ public final class FeatureFlags { + "data preparation for loading the home screen"); // TODO(Block 4): Cleanup flags - public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR = - getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED, - "Allow search bar to persist and animate across states, and attach to" - + " the keyboard from the bottom of the screen"); - public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW = getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED, "Allow entering All Apps from Overview (e.g. long swipe up from app)"); From 1ef246359eb86ee27a522c9d60e396235f18ef00 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 11 Jun 2024 18:39:18 -0700 Subject: [PATCH 105/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I6f155a2ed120e75dfcd3ed5257c63fd6c0805550 --- quickstep/res/values-af/strings.xml | 12 ++++-------- quickstep/res/values-am/strings.xml | 12 ++++-------- quickstep/res/values-ar/strings.xml | 12 ++++-------- quickstep/res/values-as/strings.xml | 12 ++++-------- quickstep/res/values-az/strings.xml | 12 ++++-------- quickstep/res/values-b+sr+Latn/strings.xml | 12 ++++-------- quickstep/res/values-be/strings.xml | 12 ++++-------- quickstep/res/values-bg/strings.xml | 12 ++++-------- quickstep/res/values-bn/strings.xml | 12 ++++-------- quickstep/res/values-bs/strings.xml | 12 ++++-------- quickstep/res/values-ca/strings.xml | 12 ++++-------- quickstep/res/values-cs/strings.xml | 14 +++++--------- quickstep/res/values-da/strings.xml | 12 ++++-------- quickstep/res/values-de/strings.xml | 12 ++++-------- quickstep/res/values-el/strings.xml | 12 ++++-------- quickstep/res/values-en-rAU/strings.xml | 12 ++++-------- quickstep/res/values-en-rCA/strings.xml | 12 ++++-------- quickstep/res/values-en-rGB/strings.xml | 12 ++++-------- quickstep/res/values-en-rIN/strings.xml | 12 ++++-------- quickstep/res/values-en-rXC/strings.xml | 12 ++++-------- quickstep/res/values-es-rUS/strings.xml | 12 ++++-------- quickstep/res/values-es/strings.xml | 12 ++++-------- quickstep/res/values-et/strings.xml | 12 ++++-------- quickstep/res/values-eu/strings.xml | 12 ++++-------- quickstep/res/values-fa/strings.xml | 12 ++++-------- quickstep/res/values-fi/strings.xml | 12 ++++-------- quickstep/res/values-fr-rCA/strings.xml | 12 ++++-------- quickstep/res/values-fr/strings.xml | 12 ++++-------- quickstep/res/values-gl/strings.xml | 12 ++++-------- quickstep/res/values-gu/strings.xml | 12 ++++-------- quickstep/res/values-hi/strings.xml | 12 ++++-------- quickstep/res/values-hr/strings.xml | 12 ++++-------- quickstep/res/values-hu/strings.xml | 12 ++++-------- quickstep/res/values-hy/strings.xml | 12 ++++-------- quickstep/res/values-in/strings.xml | 12 ++++-------- quickstep/res/values-is/strings.xml | 12 ++++-------- quickstep/res/values-it/strings.xml | 12 ++++-------- quickstep/res/values-iw/strings.xml | 12 ++++-------- quickstep/res/values-ja/strings.xml | 12 ++++-------- quickstep/res/values-ka/strings.xml | 12 ++++-------- quickstep/res/values-kk/strings.xml | 12 ++++-------- quickstep/res/values-km/strings.xml | 12 ++++-------- quickstep/res/values-kn/strings.xml | 12 ++++-------- quickstep/res/values-ko/strings.xml | 12 ++++-------- quickstep/res/values-ky/strings.xml | 12 ++++-------- quickstep/res/values-lo/strings.xml | 12 ++++-------- quickstep/res/values-lt/strings.xml | 12 ++++-------- quickstep/res/values-lv/strings.xml | 12 ++++-------- quickstep/res/values-mk/strings.xml | 12 ++++-------- quickstep/res/values-ml/strings.xml | 12 ++++-------- quickstep/res/values-mn/strings.xml | 12 ++++-------- quickstep/res/values-mr/strings.xml | 12 ++++-------- quickstep/res/values-ms/strings.xml | 12 ++++-------- quickstep/res/values-my/strings.xml | 12 ++++-------- quickstep/res/values-nb/strings.xml | 12 ++++-------- quickstep/res/values-ne/strings.xml | 12 ++++-------- quickstep/res/values-nl/strings.xml | 12 ++++-------- quickstep/res/values-or/strings.xml | 12 ++++-------- quickstep/res/values-pa/strings.xml | 12 ++++-------- quickstep/res/values-pl/strings.xml | 12 ++++-------- quickstep/res/values-pt-rPT/strings.xml | 12 ++++-------- quickstep/res/values-pt/strings.xml | 12 ++++-------- quickstep/res/values-ro/strings.xml | 12 ++++-------- quickstep/res/values-ru/strings.xml | 12 ++++-------- quickstep/res/values-si/strings.xml | 12 ++++-------- quickstep/res/values-sk/strings.xml | 12 ++++-------- quickstep/res/values-sl/strings.xml | 12 ++++-------- quickstep/res/values-sq/strings.xml | 12 ++++-------- quickstep/res/values-sr/strings.xml | 12 ++++-------- quickstep/res/values-sv/strings.xml | 12 ++++-------- quickstep/res/values-sw/strings.xml | 12 ++++-------- quickstep/res/values-ta/strings.xml | 12 ++++-------- quickstep/res/values-te/strings.xml | 12 ++++-------- quickstep/res/values-th/strings.xml | 12 ++++-------- quickstep/res/values-tl/strings.xml | 12 ++++-------- quickstep/res/values-tr/strings.xml | 12 ++++-------- quickstep/res/values-uk/strings.xml | 12 ++++-------- quickstep/res/values-ur/strings.xml | 12 ++++-------- quickstep/res/values-uz/strings.xml | 12 ++++-------- quickstep/res/values-vi/strings.xml | 12 ++++-------- quickstep/res/values-zh-rCN/strings.xml | 12 ++++-------- quickstep/res/values-zh-rHK/strings.xml | 12 ++++-------- quickstep/res/values-zh-rTW/strings.xml | 12 ++++-------- quickstep/res/values-zu/strings.xml | 12 ++++-------- 84 files changed, 337 insertions(+), 673 deletions(-) diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml index f7bf7198e1..73c8129160 100644 --- a/quickstep/res/values-af/strings.xml +++ b/quickstep/res/values-af/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}" "{count,plural, =1{Wys # rekenaarapp.}other{Wys # rekenaarapps.}}" "%1$s en %2$s" - - - - - - - - + "Borrel" + "Oorvloei" + "%1$s vanaf %2$s" + "%1$s en nog %2$d" diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml index 1700823424..f9eed3972c 100644 --- a/quickstep/res/values-am/strings.xml +++ b/quickstep/res/values-am/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}" "{count,plural, =1{# የዴስክቶፕ መተግበሪያ አሳይ።}one{# የዴስክቶፕ መተግበሪያ አሳይ።}other{# የዴስክቶፕ መተግበሪያዎች አሳይ።}}" "%1$s እና %2$s" - - - - - - - - + "አረፋ" + "ትርፍ ፍሰት" + "%1$s%2$s" + "%1$s እና %2$d ተጨማሪ" diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 38e9f701b2..7a0be9b979 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}" "{count,plural, =1{عرض تطبيق واحد متوافق مع الكمبيوتر المكتبي}zero{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}two{عرض تطبيقَين متوافقين مع الكمبيوتر المكتبي}few{عرض # تطبيقات متوافقة مع الكمبيوتر المكتبي}many{عرض # تطبيقًا متوافقًا مع الكمبيوتر المكتبي}other{عرض # تطبيق متوافق مع الكمبيوتر المكتبي}}" "\"%1$s\" و\"%2$s\"" - - - - - - - - + "فقاعة" + "القائمة الكاملة" + "‫\"%1$s\" من \"%2$s\"" + "‫\"%1$s\" و%2$d غيرها" diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml index 5ba91634ae..d440400367 100644 --- a/quickstep/res/values-as/strings.xml +++ b/quickstep/res/values-as/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{আৰু # টা এপ্‌ দেখুৱাওক।}one{আৰু # টা এপ্‌ দেখুৱাওক।}other{আৰু # টা এপ্‌ দেখুৱাওক।}}" "{count,plural, =1{# টা ডেস্কটপ এপ্ দেখুৱাওক।}one{# টা ডেস্কটপ এপ্ দেখুৱাওক।}other{# টা ডেস্কটপ এপ্ দেখুৱাওক।}}" "%1$s আৰু %2$s" - - - - - - - - + "বাবল" + "অ’ভাৰফ্ল’" + "%2$sৰ পৰা %1$s" + "%1$s আৰু %2$d টা" diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml index ab753679b6..9cdcc010f9 100644 --- a/quickstep/res/values-az/strings.xml +++ b/quickstep/res/values-az/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}" "{count,plural, =1{# masaüstü tətbiqini göstərin.}other{# masaüstü tətbiqini göstərin.}}" "%1$s%2$s" - - - - - - - - + "Yumrucuq" + "Kənara çıxma" + "%1$s, %2$s" + "%1$s və daha %2$d yumrucuq" diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml index d23ba50e0b..b6271a9a9c 100644 --- a/quickstep/res/values-b+sr+Latn/strings.xml +++ b/quickstep/res/values-b+sr+Latn/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}" "{count,plural, =1{Prikaži # aplikaciju za računare.}one{Prikaži # aplikaciju za računare.}few{Prikaži # aplikacije za računare.}other{Prikaži # aplikacija za računare.}}" "%1$s i %2$s" - - - - - - - - + "Oblačić" + "Preklopni" + "%1$s%2$s" + "%1$s i još %2$d" diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml index 2829fd9962..bb6c7641f0 100644 --- a/quickstep/res/values-be/strings.xml +++ b/quickstep/res/values-be/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}" "{count,plural, =1{Паказаць # праграму для ПК.}one{Паказаць # праграму для ПК.}few{Паказаць # праграмы для ПК.}many{Паказаць # праграм для ПК.}other{Паказаць # праграмы для ПК.}}" "%1$s і %2$s" - - - - - - - - + "Бурбалкі" + "Меню з пашырэннем" + "%1$s, крыніца: %2$s" + "%1$s і яшчэ %2$d" diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index bb7d7be7c5..d674dbcdbb 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}" "{count,plural, =1{Показване на # настолно приложение.}other{Показване на # настолни приложения.}}" "%1$s и %2$s" - - - - - - - - + "Балонче" + "Препълване" + "%1$s от %2$s" + "%1$s и още %2$d" diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml index ebde96d0ab..3e974f53f3 100644 --- a/quickstep/res/values-bn/strings.xml +++ b/quickstep/res/values-bn/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}" "{count,plural, =1{#টি ডেস্কটপ অ্যাপ দেখুন।}one{#টি ডেস্কটপ অ্যাপ দেখুন।}other{#টি ডেস্কটপ অ্যাপ দেখুন।}}" "%1$s%2$s" - - - - - - - - + "বাবল" + "ওভারফ্লো" + "%2$s থেকে %1$s" + "%1$s এবং আরও %2$dটি" diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml index 89cdc285e0..19268be2dd 100644 --- a/quickstep/res/values-bs/strings.xml +++ b/quickstep/res/values-bs/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}" "{count,plural, =1{Prikaži # aplikaciju za računar.}one{Prikaži # aplikaciju za računar.}few{Prikaži # aplikacije za računar.}other{Prikaži # aplikacija za računar.}}" "%1$s i %2$s" - - - - - - - - + "Oblačić" + "Preklopni meni" + "%1$s iz aplikacije %2$s" + "%1$s i još %2$d" diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index f1768aa47f..6a6f131858 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}" "{count,plural, =1{Mostra # aplicació per a ordinadors.}other{Mostra # aplicacions per a ordinadors.}}" "%1$s i %2$s" - - - - - - - - + "Bombolla" + "Desbordament" + "%1$s de %2$s" + "%1$s i %2$d més" diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index 6c523ca337..e1348500cc 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -73,7 +73,7 @@ "Přejeďte prstem nahoru z dolního okraje obrazovky" "Zkuste podržet okno delší dobu, než ho uvolníte" "Přejeďte prstem přímo nahoru a pak udělejte pauzu" - "Naučili jste se používat gesta. Vypnout je můžete v nastavení." + "Naučili jste se používat gesta. Vypnout je můžete v Nastavení." "Dokončili jste gesto pro přepínání aplikací" "Přepínání aplikací přejetím prstem" "Přejeďte nahoru z dolního okraje obrazovky, podržte obrazovku a uvolněte." @@ -140,12 +140,8 @@ "{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}" "{count,plural, =1{Zobrazit # aplikaci pro počítač.}few{Zobrazit # aplikace pro počítač.}many{Zobrazit # aplikace pro počítač.}other{Zobrazit # aplikací pro počítač.}}" "%1$s%2$s" - - - - - - - - + "Bublina" + "Rozbalovací nabídka" + "%1$s z aplikace %2$s" + "%1$s a ještě %2$d" diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml index a8d361212b..e9cdbce258 100644 --- a/quickstep/res/values-da/strings.xml +++ b/quickstep/res/values-da/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}" "{count,plural, =1{Vis # computerprogram.}one{Vis # computerprogram.}other{Vis # computerprogrammer.}}" "%1$s og %2$s" - - - - - - - - + "Boble" + "Overløb" + "%1$s fra %2$s" + "%1$s og %2$d mere" diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index bc15ca530a..9e5cb12596 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# weitere App anzeigen}other{# weitere Apps anzeigen}}" "{count,plural, =1{# Desktop-App anzeigen.}other{# Desktop-Apps anzeigen.}}" "%1$s und %2$s" - - - - - - - - + "Bubble" + "Weitere Optionen" + "„%1$s“ aus %2$s" + "%1$s und %2$d weitere" diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml index c317aa470c..bbb12828f3 100644 --- a/quickstep/res/values-el/strings.xml +++ b/quickstep/res/values-el/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}" "{count,plural, =1{Εμφάνιση # εφαρμογής υπολογιστή.}other{Εμφάνιση # εφαρμογών υπολογιστή.}}" "%1$s και %2$s" - - - - - - - - + "Συννεφάκι" + "Υπερχείλιση" + "%1$s από %2$s" + "%1$s και %2$d ακόμα" diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml index 519146b17b..eedb29ec84 100644 --- a/quickstep/res/values-en-rAU/strings.xml +++ b/quickstep/res/values-en-rAU/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" - - - - - - - - + "Bubble" + "Overflow" + "%1$s from %2$s" + "%1$s and %2$d more" diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml index 4205e49c6c..88cd0dd855 100644 --- a/quickstep/res/values-en-rCA/strings.xml +++ b/quickstep/res/values-en-rCA/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" - - - - - - - - + "Bubble" + "Overflow" + "%1$s from %2$s" + "%1$s and %2$d more" diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml index 519146b17b..eedb29ec84 100644 --- a/quickstep/res/values-en-rGB/strings.xml +++ b/quickstep/res/values-en-rGB/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" - - - - - - - - + "Bubble" + "Overflow" + "%1$s from %2$s" + "%1$s and %2$d more" diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml index 519146b17b..eedb29ec84 100644 --- a/quickstep/res/values-en-rIN/strings.xml +++ b/quickstep/res/values-en-rIN/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Show # more app.}other{Show # more apps.}}" "{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}" "%1$s and %2$s" - - - - - - - - + "Bubble" + "Overflow" + "%1$s from %2$s" + "%1$s and %2$d more" diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml index 44afeddbdd..76dab0d3c8 100644 --- a/quickstep/res/values-en-rXC/strings.xml +++ b/quickstep/res/values-en-rXC/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more apps.‎‏‎‎‏‎}}" "{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎Show # desktop app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎Show # desktop apps.‎‏‎‎‏‎}}" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - - - - - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‎‏‎Bubble‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎Overflow‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎%2$d‎‏‎‎‏‏‏‎ more‎‏‎‎‏‎" diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index 4930c0b6be..58d540f7bc 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}" "{count,plural, =1{Mostrar # app para computadoras.}other{Mostrar # apps para computadoras.}}" "%1$s y %2$s" - - - - - - - - + "Burbuja" + "Ampliada" + "%1$s de %2$s" + "%1$s y %2$d más" diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index 4b45f5ef07..2a956f0b48 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}" "{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicaciones para ordenadores.}}" "%1$s y %2$s" - - - - - - - - + "Burbuja" + "Menú adicional" + "%1$s de %2$s" + "%1$s y %2$d más" diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml index d6b9e7848e..0ecc0c01df 100644 --- a/quickstep/res/values-et/strings.xml +++ b/quickstep/res/values-et/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}" "{count,plural, =1{Kuva # töölauarakendus.}other{Kuva # töölauarakendust.}}" "%1$s ja %2$s" - - - - - - - - + "Mull" + "Ületäide" + "%1$s%2$s" + "%1$s ja veel %2$d mulli" diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml index bcecfeac25..e83ee28653 100644 --- a/quickstep/res/values-eu/strings.xml +++ b/quickstep/res/values-eu/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}" "{count,plural, =1{Erakutsi ordenagailuetarako # aplikazio.}other{Erakutsi ordenagailuetarako # aplikazio.}}" "%1$s eta %2$s" - - - - - - - - + "Burbuila" + "Luzapena" + "%1$s (%2$s)" + "%1$s eta beste %2$d" diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml index a68d77c856..b296080164 100644 --- a/quickstep/res/values-fa/strings.xml +++ b/quickstep/res/values-fa/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}" "{count,plural, =1{نمایش # برنامه رایانه.}one{نمایش # برنامه رایانه.}other{نمایش # برنامه رایانه.}}" "%1$s و %2$s" - - - - - - - - + "حبابک" + "سرریز" + "%1$s از %2$s" + "%1$s و %2$d حبابک دیگر" diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml index bb0516ccd3..5ac124a8ee 100644 --- a/quickstep/res/values-fi/strings.xml +++ b/quickstep/res/values-fi/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}" "{count,plural, =1{Näytä # työpöytäsovellus.}other{Näytä # työpöytäsovellusta.}}" "%1$s ja %2$s" - - - - - - - - + "Kupla" + "Ylivuoto" + "%1$s: %2$s" + "%1$s ja %2$d muuta" diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index dd36f2e5d3..edfb59ebc4 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}" "{count,plural, =1{Afficher # appli de bureau.}one{Afficher # appli de bureau.}other{Afficher # applis de bureau.}}" "%1$s et %2$s" - - - - - - - - + "Bulle" + "Bulle à développer" + "%1$s de %2$s" + "%1$s et %2$d autres" diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml index de335bfd57..60f894469e 100644 --- a/quickstep/res/values-fr/strings.xml +++ b/quickstep/res/values-fr/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Afficher # autre appli}one{Afficher # autre appli}other{Afficher # autre applis}}" "{count,plural, =1{Afficher # application de bureau.}one{Afficher # application de bureau.}other{Afficher # applications de bureau.}}" "%1$s et %2$s" - - - - - - - - + "Bulle" + "Dépassement" + "%1$s (%2$s)" + "%1$s et %2$d autre(s)" diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml index b116332d11..bf081d4e75 100644 --- a/quickstep/res/values-gl/strings.xml +++ b/quickstep/res/values-gl/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}" "{count,plural, =1{Mostrar # aplicación para ordenadores.}other{Mostrar # aplicacións para ordenadores.}}" "%1$s e %2$s" - - - - - - - - + "Burbulla" + "Menú adicional" + "%1$s de %2$s" + "%1$s e %2$d máis" diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml index efba149909..b20f77154c 100644 --- a/quickstep/res/values-gu/strings.xml +++ b/quickstep/res/values-gu/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}" "{count,plural, =1{# ડેસ્કટૉપ ઍપ બતાવો.}one{# ડેસ્કટૉપ ઍપ બતાવો.}other{# ડેસ્કટૉપ ઍપ બતાવો.}}" "%1$s અને %2$s" - - - - - - - - + "બબલ" + "ઓવરફ્લો" + "%2$sથી %1$s" + "%1$s અને વધુ %2$d" diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 205be273cf..a645186475 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}" "{count,plural, =1{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}one{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}other{# डेस्कटॉप ऐप्लिकेशन दिखाएं.}}" "%1$s और %2$s" - - - - - - - - + "बबल" + "ओवरफ़्लो" + "%2$s की %1$s वाली सूचना" + "%1$s और %2$d अन्य" diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index d189268b53..c96381d4a9 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Prikaži još # aplikaciju}one{Prikaži još # aplikaciju}few{Prikaži još # aplikacije}other{Prikaži još # aplikacija}}" "{count,plural, =1{Prikaži # računalnu aplikaciju.}one{Prikaži # računalnu aplikaciju.}few{Prikaži # računalne aplikacije.}other{Prikaži # računalnih aplikacija.}}" "%1$s i %2$s" - - - - - - - - + "Oblačić" + "Dodatni izbornik" + "%1$s, %2$s" + "%1$s i još %2$d" diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml index 975966e1de..03235aa5a6 100644 --- a/quickstep/res/values-hu/strings.xml +++ b/quickstep/res/values-hu/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}" "{count,plural, =1{# asztali alkalmazás megjelenítése.}other{# asztali alkalmazás megjelenítése.}}" "%1$s és %2$s" - - - - - - - - + "Buborék" + "Túlcsordulás" + "%1$s, forrás: %2$s" + "%1$s és %2$d további" diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml index 7e562583f9..3cb79904e4 100644 --- a/quickstep/res/values-hy/strings.xml +++ b/quickstep/res/values-hy/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}" "{count,plural, =1{Ցույց տալ # համակարգչային հավելված։}one{Ցույց տալ # համակարգչային հավելված։}other{Ցույց տալ # համակարգչային հավելված։}}" "%1$s և %2$s" - - - - - - - - + "Ամպիկ" + "Լրացուցիչ ընտրացանկ" + "%1$s՝ %2$s հավելվածից" + "%1$s ու ևս %2$d ամպիկ" diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml index d0a7a91494..015b09e1c5 100644 --- a/quickstep/res/values-in/strings.xml +++ b/quickstep/res/values-in/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Tampilkan # aplikasi lainnya.}other{Tampilkan # aplikasi lainnya.}}" "{count,plural, =1{Tampilkan # aplikasi desktop.}other{Tampilkan # aplikasi desktop.}}" "%1$s dan %2$s" - - - - - - - - + "Balon" + "Tambahan" + "%1$s dari %2$s" + "%1$s dan %2$d lainnya" diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index 34e5f26e42..883fe82647 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}" "{count,plural, =1{Sýna # skjáborðsforrit.}one{Sýna # skjáborðsforrit.}other{Sýna # skjáborðsforrit.}}" "%1$s og %2$s" - - - - - - - - + "Blaðra" + "Yfirflæði" + "%1$s frá %2$s" + "%1$s og %2$d í viðbót" diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index a5d11f856c..59b195ae61 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}" "{count,plural, =1{Mostra # app desktop.}other{Mostra # app desktop.}}" "%1$s e %2$s" - - - - - - - - + "Fumetto" + "Extra" + "%1$s da %2$s" + "%1$s e altri %2$d" diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml index 30c53d5bdd..9f0ed1453a 100644 --- a/quickstep/res/values-iw/strings.xml +++ b/quickstep/res/values-iw/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}" "{count,plural, =1{הצגת אפליקציה אחת (#) למחשב.}one{הצגת # אפליקציות למחשב.}two{הצגת # אפליקציות למחשב.}other{הצגת # אפליקציות למחשב.}}" "%1$s ו-%2$s" - - - - - - - - + "בועה" + "אפשרויות נוספות" + "‫%1$s מתוך %2$s" + "‫%1$s ועוד %2$d" diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml index ead3c19208..4f1a162c3f 100644 --- a/quickstep/res/values-ja/strings.xml +++ b/quickstep/res/values-ja/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}" "{count,plural, =1{# 個のデスクトップ アプリが表示されます。}other{# 個のデスクトップ アプリが表示されます。}}" "%1$s%2$s" - - - - - - - - + "ふきだし" + "オーバーフロー" + "%1$s%2$s)" + "%1$s、他 %2$d 件" diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml index bcc28b489c..1fb60773eb 100644 --- a/quickstep/res/values-ka/strings.xml +++ b/quickstep/res/values-ka/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}" "{count,plural, =1{# დესკტოპის აპის ჩვენება.}other{# დესკტოპის აპის ჩვენება.}}" "%1$s და %2$s" - - - - - - - - + "ბუშტი" + "გადავსება" + "%1$s: %2$s-იდან" + "%1$s და %2$d სხვა" diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index 0002024413..d83e2d346a 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}" "{count,plural, =1{Компьютерге арналған # қолданбаны көрсету}other{Компьютерге арналған # қолданбаны көрсету}}" "%1$s және %2$s" - - - - - - - - + "Қалқыма терезе" + "Қосымша мәзір" + "%2$s ұсынатын %1$s" + "%1$s және тағы %2$d" diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index 8c38c48777..5448433044 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញ​កម្មវិធី # ទៀត។}}" "{count,plural, =1{បង្ហាញកម្មវិធី​កុំព្យូទ័រ #។}other{បង្ហាញកម្មវិធី​កុំព្យូទ័រ #។}}" "%1$s និង %2$s" - - - - - - - - + "ផ្ទាំងសារ" + "ម៉ឺនុយបន្ថែម" + "%1$s ពី %2$s" + "%1$s និង %2$d នាក់ទៀត" diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml index 1231157c2e..74c77506fb 100644 --- a/quickstep/res/values-kn/strings.xml +++ b/quickstep/res/values-kn/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}" "{count,plural, =1{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್ ತೋರಿಸಿ.}one{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{# ಡೆಸ್ಕ್‌ಟಾಪ್ ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}" "%1$s ಮತ್ತು %2$s" - - - - - - - - + "ಬಬಲ್" + "ಓವರ್‌ಫ್ಲೋ" + "%2$s ನಿಂದ %1$s" + "%1$s ಮತ್ತು ಇನ್ನೂ %2$d" diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml index e0fc21f0c3..1f4275a2d7 100644 --- a/quickstep/res/values-ko/strings.xml +++ b/quickstep/res/values-ko/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}" "{count,plural, =1{데스크톱 앱 #개를 표시합니다.}other{데스크톱 앱 #개를 표시합니다.}}" "%1$s%2$s" - - - - - - - - + "풍선" + "오버플로" + "%2$s%1$s" + "%1$s%2$d개" diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index fbb1c42ff6..f0d2af8935 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}" "{count,plural, =1{# иш такта колдонмосун көрсөтүү.}other{# иш такта колдонмосун көрсөтүү.}}" "%1$s жана %2$s" - - - - - - - - + "Көбүкчө" + "Кошумча меню" + "%2$s колдонмосунан %1$s" + "%1$s жана дагы %2$d" diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml index bb363300ae..f54c7121f5 100644 --- a/quickstep/res/values-lo/strings.xml +++ b/quickstep/res/values-lo/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}" "{count,plural, =1{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}other{ສະແດງແອັບເດັສທັອບ # ລາຍການ.}}" "%1$s ແລະ %2$s" - - - - - - - - + "ຟອງ" + "ລາຍການເພີ່ມເຕີມ" + "%1$s ຈາກ %2$s" + "%1$s ແລະ ອີກ %2$d ລາຍການ" diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml index b5dceb6415..554745e732 100644 --- a/quickstep/res/values-lt/strings.xml +++ b/quickstep/res/values-lt/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}" "{count,plural, =1{Rodyti # darbalaukio programą.}one{Rodyti # darbalaukio programą.}few{Rodyti # darbalaukio programas.}many{Rodyti # darbalaukio programos.}other{Rodyti # darbalaukio programų.}}" "„%1$s“ ir „%2$s“" - - - - - - - - + "Burbulas" + "Perpildymas" + "„%1$s“ iš „%2$s“" + "„%1$s“ ir dar %2$d" diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml index 2b6208a629..a6a0dab930 100644 --- a/quickstep/res/values-lv/strings.xml +++ b/quickstep/res/values-lv/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}" "{count,plural, =1{Rādīt # datora lietotni.}zero{Rādīt # datora lietotnes.}one{Rādīt # datora lietotni.}other{Rādīt # datora lietotnes.}}" "“%1$s” un “%2$s”" - - - - - - - - + "Burbulis" + "Pārpilde" + "%1$s no lietotnes %2$s" + "%1$s un vēl %2$d" diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml index 6b8c592ff8..4859055e94 100644 --- a/quickstep/res/values-mk/strings.xml +++ b/quickstep/res/values-mk/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}" "{count,plural, =1{Прикажи # апликација за компјутер.}one{Прикажи # апликација за компјутер.}other{Прикажи # апликации за компјутер.}}" "%1$s и %2$s" - - - - - - - - + "Балонче" + "Проширено балонче" + "%1$s од %2$s" + "%1$s и уште %2$d" diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml index d401c20aaa..85b093d6fa 100644 --- a/quickstep/res/values-ml/strings.xml +++ b/quickstep/res/values-ml/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}" "{count,plural, =1{# ഡെസ്‌ക്ടോപ്പ് ആപ്പ് കാണിക്കുക.}other{# ഡെസ്‌ക്ടോപ്പ് ആപ്പുകൾ കാണിക്കുക.}}" "%1$s, %2$s" - - - - - - - - + "ബബിൾ" + "ഓവർഫ്ലോ" + "%2$s എന്നതിൽ നിന്നുള്ള %1$s" + "%1$s എന്നതും മറ്റ് %2$d എണ്ണവും" diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml index 4491c37531..7a4c7e9cd6 100644 --- a/quickstep/res/values-mn/strings.xml +++ b/quickstep/res/values-mn/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}" "{count,plural, =1{Компьютерын # аппыг харуулна уу.}other{Компьютерын # аппыг харуулна уу.}}" "%1$s болон %2$s" - - - - - - - - + "Бөмбөлөг" + "Урт цэс" + "%2$s-с ирсэн %1$s" + "%1$s болон бусад %2$d" diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index 3938fd4dc7..7941156dbc 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{आणखी # अ‍ॅप दाखवा.}other{आणखी # अ‍ॅप्स दाखवा.}}" "{count,plural, =1{# डेस्‍कटॉप अ‍ॅप दाखवा.}other{# डेस्‍कटॉप अ‍ॅप्स दाखवा.}}" "%1$s आणि %2$s" - - - - - - - - + "बबल" + "ओव्हरफ्लो" + "%2$s वरील %1$s" + "%1$s आणि आणखी %2$d" diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml index 0db53d6579..c0219e04fc 100644 --- a/quickstep/res/values-ms/strings.xml +++ b/quickstep/res/values-ms/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}" "{count,plural, =1{Tunjukkan # apl desktop.}other{Tunjukkan # apl desktop.}}" "%1$s dan %2$s" - - - - - - - - + "Gelembung" + "Limpahan" + "%1$s daripada %2$s" + "%1$s dan %2$d lagi" diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index 4ac838a794..7c7ff82b85 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}" "{count,plural, =1{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}other{ဒက်စတော့ အက်ပ် # ခု ပြပါ။}}" "%1$s နှင့် %2$s" - - - - - - - - + "ပူဖောင်းကွက်" + "မီနူးအပို" + "%2$s မှ %1$s" + "%1$s နှင့် နောက်ထပ် %2$d ခု" diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index 46bf14b5b5..dd3d16e18a 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Vis # app til.}other{Vis # apper til.}}" "{count,plural, =1{Vis # datamaskinprogram.}other{Vis # datamaskinprogrammer.}}" "%1$s og %2$s" - - - - - - - - + "Boble" + "Overflyt" + "%1$s fra %2$s" + "%1$s og %2$d andre" diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index 07437caf19..d49fd2d53e 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{थप # एप देखाउनुहोस्।}other{थप # वटा एप देखाउनुहोस्।}}" "{count,plural, =1{# डेस्कटप एप देखाउनुहोस्।}other{# वटा डेस्कटप एप देखाउनुहोस्।}}" "%1$s%2$s" - - - - - - - - + "बबल" + "ओभरफ्लो" + "%2$s मा देखाइएका %1$s" + "%1$s र थप %2$d" diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml index 3dedd7b040..ca44a6914c 100644 --- a/quickstep/res/values-nl/strings.xml +++ b/quickstep/res/values-nl/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}" "{count,plural, =1{# desktop-app tonen.}other{# desktop-apps tonen.}}" "%1$s en %2$s" - - - - - - - - + "Bubbel" + "Overloop" + "%1$s van %2$s" + "%1$s en nog %2$d" diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml index 67a5b139d4..bf0bdc8323 100644 --- a/quickstep/res/values-or/strings.xml +++ b/quickstep/res/values-or/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}" "{count,plural, =1{# ଡେସ୍କଟପ ଆପ ଦେଖାନ୍ତୁ।}other{# ଡେସ୍କଟପ ଆପ୍ସ ଦେଖାନ୍ତୁ।}}" "%1$s ଏବଂ %2$s" - - - - - - - - + "ବବଲ" + "ଓଭରଫ୍ଲୋ" + "%2$sରୁ %1$s" + "%1$s ଏବଂ ଅଧିକ %2$d" diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml index 78f1c7951f..fc603969a7 100644 --- a/quickstep/res/values-pa/strings.xml +++ b/quickstep/res/values-pa/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}" "{count,plural, =1{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}one{# ਡੈਸਕਟਾਪ ਐਪ ਦਿਖਾਓ।}other{# ਡੈਸਕਟਾਪ ਐਪਾਂ ਦਿਖਾਓ।}}" "%1$s ਅਤੇ %2$s" - - - - - - - - + "ਬਬਲ" + "ਓਵਰਫ਼ਲੋ" + "%2$s ਤੋਂ %1$s" + "%1$s ਅਤੇ %2$d ਹੋਰ" diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml index 41ac736ce6..d88e28ac3b 100644 --- a/quickstep/res/values-pl/strings.xml +++ b/quickstep/res/values-pl/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}" "{count,plural, =1{Pokaż # aplikację komputerową.}few{Pokaż # aplikacje komputerowe.}many{Pokaż # aplikacji komputerowych.}other{Pokaż # aplikacji komputerowej.}}" "%1$s%2$s" - - - - - - - - + "Dymek" + "Rozwijany" + "%1$s z aplikacji %2$s" + "%1$s i jeszcze %2$d" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index f674d687f3..dd00469e41 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}" "{count,plural, =1{Mostrar # app para computador.}other{Mostrar # apps para computador.}}" "%1$s e %2$s" - - - - - - - - + "Balão" + "Menu adicional" + "%1$s da app %2$s" + "%1$s e mais %2$d pessoas" diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index 4f3d75ade1..4fec4f8511 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}" "{count,plural, =1{Mostrar # app para computador.}one{Mostrar # app para computador.}other{Mostrar # apps para computador.}}" "%1$s e %2$s" - - - - - - - - + "Balão" + "Balão flutuante" + "%1$s do app %2$s" + "%1$s e mais %2$d" diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml index dee1ac613e..c839602e89 100644 --- a/quickstep/res/values-ro/strings.xml +++ b/quickstep/res/values-ro/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}" "{count,plural, =1{Afișează # aplicație pentru computer.}few{Afișează # aplicații pentru computer.}other{Afișează # de aplicații pentru computer.}}" "%1$s și %2$s" - - - - - - - - + "Balon" + "Suplimentar" + "%1$s de la %2$s" + "%1$s și încă %2$d" diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml index a78561a687..da49ad32b8 100644 --- a/quickstep/res/values-ru/strings.xml +++ b/quickstep/res/values-ru/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}" "{count,plural, =1{Показать # компьютерное приложение.}one{Показать # компьютерное приложение.}few{Показать # компьютерных приложения.}many{Показать # компьютерных приложений.}other{Показать # компьютерного приложения.}}" "%1$s и %2$s" - - - - - - - - + "Всплывающая подсказка" + "Дополнительное меню" + "\"%1$s\" из приложения \"%2$s\"" + "%1$s и ещё %2$d" diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml index c1dfa9df78..9cbe837f94 100644 --- a/quickstep/res/values-si/strings.xml +++ b/quickstep/res/values-si/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}" "{count,plural, =1{# ඩෙස්ක්ටොප් යෙදුමක් පෙන්වන්න.}one{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}other{ඩෙස්ක්ටොප් යෙදුම් # ක් පෙන්වන්න.}}" "%1$s සහ %2$s" - - - - - - - - + "බුබුළු" + "පිටාර යාම" + "%2$s සිට %1$s" + "%1$s හා තව %2$dක්" diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml index 51f09aa1a8..3eca787fed 100644 --- a/quickstep/res/values-sk/strings.xml +++ b/quickstep/res/values-sk/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}" "{count,plural, =1{Zobraziť # aplikáciu pre počítač.}few{Zobraziť # aplikácie pre počítač.}many{Show # desktop apps.}other{Zobraziť # aplikácií pre počítač.}}" "%1$s%2$s" - - - - - - - - + "Bublina" + "Rozbaľovacia ponuka" + "%1$s z aplikácie %2$s" + "%1$s a ešte %2$d" diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml index ea1fd45cbe..52faeb7a9e 100644 --- a/quickstep/res/values-sl/strings.xml +++ b/quickstep/res/values-sl/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}" "{count,plural, =1{Prikaz # aplikacije za namizni računalnik.}one{Prikaz # aplikacije za namizni računalnik.}two{Prikaz # aplikacij za namizni računalnik.}few{Prikaz # aplikacij za namizni računalnik.}other{Prikaz # aplikacij za namizni računalnik.}}" "%1$s in %2$s" - - - - - - - - + "Oblaček" + "Oblaček z dodatnimi elementi" + "%1$s iz aplikacije %2$s" + "%1$s in še %2$d" diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml index 6cc894a2d0..cdb9cf9a7c 100644 --- a/quickstep/res/values-sq/strings.xml +++ b/quickstep/res/values-sq/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}" "{count,plural, =1{Shfaq # aplikacion për desktop.}other{Shfaq # aplikacione për desktop.}}" "%1$s dhe %2$s" - - - - - - - - + "Flluska" + "Tejkalimi" + "\"%1$s\" nga %2$s" + "\"%1$s\" dhe %2$d të tjera" diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml index 7828868511..7456a36b7e 100644 --- a/quickstep/res/values-sr/strings.xml +++ b/quickstep/res/values-sr/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}" "{count,plural, =1{Прикажи # апликацију за рачунаре.}one{Прикажи # апликацију за рачунаре.}few{Прикажи # апликације за рачунаре.}other{Прикажи # апликација за рачунаре.}}" "%1$s и %2$s" - - - - - - - - + "Облачић" + "Преклопни" + "%1$s%2$s" + "%1$s и још %2$d" diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index 4fecddd977..f369daeb33 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Visa # app till.}other{Visa # appar till.}}" "{count,plural, =1{Visa # datorapp.}other{Visa # datorappar.}}" "%1$s och %2$s" - - - - - - - - + "Bubbla" + "Fler alternativ" + "%1$s från %2$s" + "%1$s och %2$d till" diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml index 3c4e5e538d..3d8277b448 100644 --- a/quickstep/res/values-sw/strings.xml +++ b/quickstep/res/values-sw/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}" "{count,plural, =1{Onyesha programu # ya kompyuta ya mezani.}other{Onyesha programu # za kompyuta ya mezani.}}" "%1$s na %2$s" - - - - - - - - + "Kiputo" + "Kiputo cha vipengee vya ziada" + "%1$s kutoka %2$s" + "%1$s na vingine %2$d" diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml index b259dbf124..ed3ebeedaa 100644 --- a/quickstep/res/values-ta/strings.xml +++ b/quickstep/res/values-ta/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}" "{count,plural, =1{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}other{# டெஸ்க்டாப் ஆப்ஸைக் காட்டு.}}" "%1$s மற்றும் %2$s" - - - - - - - - + "குமிழ்" + "கூடுதல் விருப்பங்களைக் காட்டும்" + "%2$s வழங்கும் %1$s" + "%1$s மற்றும் %2$d" diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index 20fc77da8b..a4e1cbf09c 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{మరో # యాప్‌ను చూడండి.}other{మరో # యాప్‌లను చూడండి.}}" "{count,plural, =1{# డెస్క్‌టాప్ యాప్‌ను చూపండి.}other{# డెస్క్‌టాప్ యాప్‌లను చూపండి.}}" "%1$s, %2$s" - - - - - - - - + "బబుల్" + "ఓవర్‌ఫ్లో" + "%2$s నుండి %1$s" + "%1$s, మరో %2$d" diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml index 4adcc525cb..1bbb137a1b 100644 --- a/quickstep/res/values-th/strings.xml +++ b/quickstep/res/values-th/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}" "{count,plural, =1{แสดงแอปบนเดสก์ท็อป # รายการ}other{แสดงแอปบนเดสก์ท็อป # รายการ}}" "%1$s และ %2$s" - - - - - - - - + "บับเบิล" + "การดำเนินการเพิ่มเติม" + "%1$s จาก %2$s" + "%1$s และอีก %2$d รายการ" diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml index 66ecc00a6c..978a5a37f8 100644 --- a/quickstep/res/values-tl/strings.xml +++ b/quickstep/res/values-tl/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}" "{count,plural, =1{Ipakita ang # desktop app.}one{Ipakita ang # desktop app.}other{Ipakita ang # na desktop app.}}" "%1$s at %2$s" - - - - - - - - + "Bubble" + "Overflow" + "%1$s mula sa %2$s" + "%1$s at %2$d pa" diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml index dc5fa6bca7..0cc5d7f856 100644 --- a/quickstep/res/values-tr/strings.xml +++ b/quickstep/res/values-tr/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}" "{count,plural, =1{# masaüstü uygulamasını göster.}other{# masaüstü uygulamasını göster.}}" "%1$s ve %2$s" - - - - - - - - + "Balon" + "Taşma" + "%2$s uygulamasından %1$s" + "%1$s ve %2$d tane daha" diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml index 5119e565de..9c706a8403 100644 --- a/quickstep/res/values-uk/strings.xml +++ b/quickstep/res/values-uk/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}" "{count,plural, =1{Показати # комп’ютерну програму.}one{Показати # комп’ютерну програму.}few{Показати # комп’ютерні програми.}many{Показати # комп’ютерних програм.}other{Показати # комп’ютерної програми.}}" "%1$s та %2$s" - - - - - - - - + "Повідомлення" + "Додаткове повідомлення" + "%1$s з додатка %2$s" + "%1$s і ще %2$d" diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml index c42a601758..e12524868f 100644 --- a/quickstep/res/values-ur/strings.xml +++ b/quickstep/res/values-ur/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}" "{count,plural, =1{# ڈیسک ٹاپ ایپ دکھائیں۔}other{# ڈیسک ٹاپ ایپس دکھائیں۔}}" "%1$s اور %2$s" - - - - - - - - + "ببل" + "اوورفلو" + "%2$s سے %1$s" + "%1$s اور %2$d مزید" diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml index 810c8f04b3..3f4f981095 100644 --- a/quickstep/res/values-uz/strings.xml +++ b/quickstep/res/values-uz/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}" "{count,plural, =1{# ta desktop ilovani chiqarish.}other{# ta desktop ilovani chiqarish.}}" "%1$s va %2$s" - - - - - - - - + "Pufak" + "Kengaytirish" + "%1$s (%2$s)" + "%1$s va yana %2$d kishi" diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml index 8291ac7552..9bc526faac 100644 --- a/quickstep/res/values-vi/strings.xml +++ b/quickstep/res/values-vi/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}" "{count,plural, =1{Hiện # ứng dụng dành cho máy tính.}other{Hiện # ứng dụng dành cho máy tính.}}" "%1$s%2$s" - - - - - - - - + "Bong bóng" + "Bong bóng bổ sung" + "%1$s từ %2$s" + "%1$s%2$d bong bóng khác" diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index e00e932f2b..a89227e17e 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}" "{count,plural, =1{显示 # 款桌面应用。}other{显示 # 款桌面应用。}}" "%1$s%2$s" - - - - - - - - + "气泡框" + "菜单" + "来自“%2$s”的%1$s" + "%1$s以及另外 %2$d 个" diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index 3a7736979c..b9d8eb765a 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}" "{count,plural, =1{顯示 # 個桌面應用程式。}other{顯示 # 個桌面應用程式。}}" "「%1$s」和「%2$s」" - - - - - - - - + "對話氣泡" + "展開式" + "%2$s 的「%1$s」通知" + "%1$s和其他 %2$d 則通知" diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index 3b5996698f..90140cb587 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{再多顯示 # 個應用程式。}other{再多顯示 # 個應用程式。}}" "{count,plural, =1{顯示 # 個電腦版應用程式。}other{顯示 # 個電腦版應用程式。}}" "「%1$s」和「%2$s」" - - - - - - - - + "泡泡" + "溢位" + "「%2$s」的「%1$s」通知" + "%1$s和另外 %2$d 則通知" diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml index b3ef1e7199..73be445a55 100644 --- a/quickstep/res/values-zu/strings.xml +++ b/quickstep/res/values-zu/strings.xml @@ -140,12 +140,8 @@ "{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}" "{count,plural, =1{Bonisa i-app engu-# yedeskithophu.}one{Bonisa ama-app angu-# wedeskithophu.}other{Bonisa ama-app angu-# wedeskithophu.}}" "I-%1$s ne-%2$s" - - - - - - - - + "Ibhamuza" + "Ukugcwala kakhulu" + "%1$s kusuka ku-%2$s" + "%1$s nokunye okungu-%2$d" From ffbadc5404d6c200cdd69bd7b8a3f688d1b4f0a4 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 11 Jun 2024 18:39:45 -0700 Subject: [PATCH 106/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I1750b036138658c8abe54de9bea4f35b56fe230f --- quickstep/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index 0a6bb66170..08eda2c73b 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -72,7 +72,7 @@ "Přejeďte prstem nahoru z dolního okraje obrazovky" "Zkuste podržet okno delší dobu, než ho uvolníte" "Přejeďte prstem přímo nahoru a pak udělejte pauzu" - "Naučili jste se používat gesta. Vypnout je můžete v nastavení." + "Naučili jste se používat gesta. Vypnout je můžete v Nastavení." "Dokončili jste gesto pro přepínání aplikací" "Přepínání aplikací přejetím prstem" "Přejeďte nahoru z dolního okraje obrazovky, podržte obrazovku a uvolněte." From 27425d6623d710a94523b26353e82bd9fac03108 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 11 Jun 2024 18:40:44 -0700 Subject: [PATCH 107/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I1ddf23b707c50d756a14f677e57da5b0a008cbd0 --- res/values-bs/strings.xml | 2 +- res/values-de/strings.xml | 2 +- res/values-fi/strings.xml | 4 ++-- res/values-fr/strings.xml | 2 +- res/values-hi/strings.xml | 2 +- res/values-iw/strings.xml | 2 +- res/values-nl/strings.xml | 2 +- res/values-pt/strings.xml | 2 +- res/values-ta/strings.xml | 2 +- res/values-tr/strings.xml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index e838b29b75..325d65d006 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -192,6 +192,6 @@ "Privatno, zaključano." "Zaključaj" "Prelazak u privatan prostor" - "Instaliraj" + "Instalirajte" "Instaliranje aplikacija u privatni prostor" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index ec2285d8be..7f8924644e 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -186,7 +186,7 @@ "Fehler: %1$s" "Vertrauliches Profil" "Zum Einrichten oder Öffnen tippen" - "Privat" + "Vertraulich" "Einstellungen für vertrauliches Profil" "Privat, entsperrt." "Privat, gesperrt." diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 5ff367e70c..00880b026d 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -48,7 +48,7 @@ "Kaikki tarvittava" "Uutiset ja aikakauslehdet" "Viihde" - "Sosiaalinen" + "Some" "Sinulle ehdotetut" "%1$s widgetit oikealla, haku ja vaihtoehdot vasemmalla" "{count,plural, =1{# widget}other{# widgetiä}}" @@ -85,7 +85,7 @@ "Poista asennus" "Sovelluksen tiedot" "Asenna yksityisesti" - "Sovelluksen poistaminen" + "Poista sovellus" "Asenna" "Älä ehdota sovellusta" "Kiinnitä sovellus" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 0ea277b1f2..580d02f03c 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -85,7 +85,7 @@ "Désinstaller" "Infos sur l\'appli" "Installer en mode privé" - "Désinstaller l\'application" + "Désinstaller l\'appli" "Installer" "Ne pas suggérer d\'appli" "Épingler la prédiction" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index b5042606c5..f1117ba6c8 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -49,7 +49,7 @@ "खबरों और पत्रिकाओं वाले ऐप्लिकेशन" "मनोरंजन से जुड़े ऐप्लिकेशन" "सोशल मीडिया ऐप्लिकेशन" - "आपके लिए सुझाए गए ऐप्लिकेशन" + "आपके लिए सुझाए गए" "%1$s के विजेट दाईं ओर, खोज का विजेट और अन्य विकल्प बाईं ओर" "{count,plural, =1{# विजेट}one{# विजेट}other{# विजेट}}" "{count,plural, =1{# शॉर्टकट}one{# शॉर्टकट}other{# शॉर्टकट}}" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 21581c37e6..e00e851fa9 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -83,7 +83,7 @@ "רשימת אפליקציות עבודה" "הסרה" "להסרת התקנה" - "פרטי אפליקציה" + "פרטי האפליקציה" "התקנה במרחב הפרטי" "הסרת האפליקציה" "התקנה" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index d7d4e7de23..c2e5ebda96 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -88,7 +88,7 @@ "App verwijderen" "Installeren" "Geen app voorstellen" - "Vastzetvoorspelling" + "Voorspelling vastzetten" "Snelle links instellen" "Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker." "instellingen en snelkoppelingen op startscherm lezen" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index a049a80c09..a7eb0a71a6 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -184,7 +184,7 @@ "Ativar" "Filtrar" "Falha: %1$s" - "Espaço particular" + "Espaço privado" "Toque para configurar ou abrir" "Particular" "Configurações do Espaço particular" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index ebc55caa11..c45b3ddb87 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -192,6 +192,6 @@ "தனிப்பட்டது, லாக் செய்யப்பட்டுள்ளது." "பூட்டு" "தனிப்பட்ட சேமிப்பிடத்திற்கு மாற்றுகிறது" - "நிறுவுதல்" + "நிறுவுக" "தனிப்பட்ட சேமிப்பிடத்தில் ஆப்ஸை நிறுவும்" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 0681e3d60a..e8c7593912 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -85,7 +85,7 @@ "Kaldır" "Uygulama bilgileri" "Özel olarak yükle" - "Uygulamanın yüklemesini kaldır" + "Uygulamayı kaldır" "Yükle" "Uygulamayı önerme" "Tahmini Sabitle" From bb038c1e561cee79d22133662a116de65e413cd4 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 11 Jun 2024 18:41:11 -0700 Subject: [PATCH 108/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I8e7c673b15469c477edbba5f411be7651397ded1 --- res/values-de/strings.xml | 2 +- res/values-iw/strings.xml | 2 +- res/values-nl/strings.xml | 2 +- res/values-pt/strings.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index ef66bafbdd..b1d300ca3b 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -185,7 +185,7 @@ "Fehler: %1$s" "Vertrauliches Profil" "Hier kannst du deine privaten Apps verbergen und sperren" - "Privat" + "Vertraulich" "Einstellungen für vertrauliches Profil" "Vertrauliches Profil sperren/entsperren" "Sperren" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 725c144255..88abfee184 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -83,7 +83,7 @@ "רשימת אפליקציות עבודה" "הסרה" "להסרת התקנה" - "פרטי אפליקציה" + "פרטי האפליקציה" "התקנה במרחב הפרטי" "התקנה" "בלי להציע את האפליקציה" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 6c3b1d6610..90f65ffc48 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -87,7 +87,7 @@ "Privé installeren" "Installeren" "Geen app voorstellen" - "Vastzetvoorspelling" + "Voorspelling vastzetten" "Snelle links instellen" "Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker." "instellingen en snelkoppelingen op startscherm lezen" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index f7ef6ec079..67eb4a1914 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -183,7 +183,7 @@ "Ativar" "Filtrar" "Falha: %1$s" - "Espaço particular" + "Espaço privado" "Mantenha apps particulares bloqueados e ocultos" "Particular" "Configurações do Espaço particular" From 9eaae4b6a418ebef7db49fc6be4ffae02b9d1f6a Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Mon, 3 Jun 2024 23:20:07 +0000 Subject: [PATCH 109/143] Initial TaskbarUnitTestRule with example overlay controller tests. Flag: TEST_ONLY Bug: 230027385 Test: TaskbarOverlayControllerTest Change-Id: I858906ece7e67677962ec8b4432bfcca5ec30283 --- .../taskbar/TaskbarActivityContext.java | 5 + .../launcher3/taskbar/TaskbarManager.java | 6 +- .../overlay/TaskbarOverlayController.java | 28 ++- .../launcher3/taskbar/TaskbarUnitTestRule.kt | 144 ++++++++++++ .../overlay/TaskbarOverlayControllerTest.kt | 215 ++++++++++++++++++ 5 files changed, 387 insertions(+), 11 deletions(-) create mode 100644 quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt create mode 100644 quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 0de0550016..d536e8414f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -1605,4 +1605,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { boolean canToggleHomeAllApps() { return mControllers.uiController.canToggleHomeAllApps(); } + + @VisibleForTesting + public TaskbarControllers getControllers() { + return mControllers; + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index ec2cee2bd9..2a58db25df 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -611,7 +611,8 @@ public class TaskbarManager { } } - private void addTaskbarRootViewToWindow() { + @VisibleForTesting + void addTaskbarRootViewToWindow() { if (enableTaskbarNoRecreate() && !mAddedWindow && mTaskbarActivityContext != null) { mWindowManager.addView(mTaskbarRootLayout, mTaskbarActivityContext.getWindowLayoutParams()); @@ -619,7 +620,8 @@ public class TaskbarManager { } } - private void removeTaskbarRootViewFromWindow() { + @VisibleForTesting + void removeTaskbarRootViewFromWindow() { if (enableTaskbarNoRecreate() && mAddedWindow) { mWindowManager.removeViewImmediate(mTaskbarRootLayout); mAddedWindow = false; diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java index adbec65ad3..7eb34a51c8 100644 --- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java +++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java @@ -133,16 +133,19 @@ public final class TaskbarOverlayController { *

* This method should be called after an exit animation finishes, if applicable. */ - @SuppressLint("WrongConstant") void maybeCloseWindow() { - if (mOverlayContext != null && (AbstractFloatingView.hasOpenView(mOverlayContext, TYPE_ALL) - || mOverlayContext.getDragController().isSystemDragInProgress())) { - return; - } + if (!canCloseWindow()) return; mProxyView.close(false); onDestroy(); } + @SuppressLint("WrongConstant") + private boolean canCloseWindow() { + if (mOverlayContext == null) return true; + if (AbstractFloatingView.hasOpenView(mOverlayContext, TYPE_ALL)) return false; + return !mOverlayContext.getDragController().isSystemDragInProgress(); + } + /** Destroys the controller and any overlay window if present. */ public void onDestroy() { TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener); @@ -212,10 +215,17 @@ public final class TaskbarOverlayController { @Override protected void handleClose(boolean animate) { - if (mIsOpen) { - mTaskbarContext.getDragLayer().removeView(this); - Optional.ofNullable(mOverlayContext).ifPresent(c -> closeAllOpenViews(c, animate)); - } + if (!mIsOpen) return; + mTaskbarContext.getDragLayer().removeView(this); + Optional.ofNullable(mOverlayContext).ifPresent(c -> { + if (canCloseWindow()) { + onDestroy(); // Window is already ready to be destroyed. + } else { + // Close window's AFVs before destroying it. Its drag layer will attempt to + // close the proxy view again once its children are removed. + closeAllOpenViews(c, animate); + } + }); } @Override diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt new file mode 100644 index 0000000000..77cd1fe67a --- /dev/null +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt @@ -0,0 +1,144 @@ +/* + * 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.taskbar + +import android.app.PendingIntent +import android.content.IIntentSender +import android.content.Intent +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ServiceTestRule +import com.android.launcher3.LauncherAppState +import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks +import com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR +import com.android.launcher3.util.LauncherMultivalentJUnit.Companion.isRunningInRobolectric +import com.android.quickstep.AllAppsActionManager +import com.android.quickstep.TouchInteractionService +import com.android.quickstep.TouchInteractionService.TISBinder +import org.junit.Assume.assumeTrue +import org.junit.rules.MethodRule +import org.junit.runners.model.FrameworkMethod +import org.junit.runners.model.Statement + +/** + * Manages the Taskbar lifecycle for unit tests. + * + * See [InjectController] for grabbing controller(s) under test with minimal boilerplate. + */ +class TaskbarUnitTestRule : MethodRule { + private val instrumentation = InstrumentationRegistry.getInstrumentation() + private val serviceTestRule = ServiceTestRule() + + private lateinit var taskbarManager: TaskbarManager + private lateinit var target: Any + + val activityContext: TaskbarActivityContext + get() { + return taskbarManager.currentActivityContext + ?: throw RuntimeException("Failed to obtain TaskbarActivityContext.") + } + + override fun apply(base: Statement, method: FrameworkMethod, target: Any): Statement { + return object : Statement() { + override fun evaluate() { + this@TaskbarUnitTestRule.target = target + + val context = instrumentation.targetContext + instrumentation.runOnMainSync { + assumeTrue( + LauncherAppState.getIDP(context).getDeviceProfile(context).isTaskbarPresent + ) + } + + // Check for existing Taskbar instance from Launcher process. + val launcherTaskbarManager: TaskbarManager? = + if (!isRunningInRobolectric) { + try { + val tisBinder = + serviceTestRule.bindService( + Intent(context, TouchInteractionService::class.java) + ) as? TISBinder + tisBinder?.taskbarManager + } catch (_: Exception) { + null + } + } else { + null + } + + instrumentation.runOnMainSync { + taskbarManager = + TaskbarManager( + context, + AllAppsActionManager(context, UI_HELPER_EXECUTOR) { + PendingIntent(IIntentSender.Default()) + }, + object : TaskbarNavButtonCallbacks {}, + ) + } + + try { + // Replace Launcher Taskbar window with test instance. + instrumentation.runOnMainSync { + launcherTaskbarManager?.removeTaskbarRootViewFromWindow() + taskbarManager.onUserUnlocked() // Required to complete initialization. + } + + injectControllers() + base.evaluate() + } finally { + // Revert Taskbar window. + instrumentation.runOnMainSync { + taskbarManager.destroy() + launcherTaskbarManager?.addTaskbarRootViewToWindow() + } + } + } + } + } + + /** Simulates Taskbar recreation lifecycle. */ + fun recreateTaskbar() { + taskbarManager.recreateTaskbar() + injectControllers() + } + + private fun injectControllers() { + val controllers = activityContext.controllers + val controllerFieldsByType = controllers.javaClass.fields.associateBy { it.type } + target.javaClass.fields + .filter { it.isAnnotationPresent(InjectController::class.java) } + .forEach { + it.set( + target, + controllerFieldsByType[it.type]?.get(controllers) + ?: throw NoSuchElementException("Failed to find controller for ${it.type}"), + ) + } + } + + /** + * Annotates test controller fields to inject the corresponding controllers from the current + * [TaskbarControllers] instance. + * + * Controllers are injected during test setup and upon calling [recreateTaskbar]. + * + * Multiple controllers can be injected if needed. + */ + @Retention(AnnotationRetention.RUNTIME) + @Target(AnnotationTarget.FIELD) + annotation class InjectController +} diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt new file mode 100644 index 0000000000..8768cb974b --- /dev/null +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt @@ -0,0 +1,215 @@ +/* + * 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.taskbar.overlay + +import android.app.ActivityManager.RunningTaskInfo +import android.view.MotionEvent +import androidx.test.annotation.UiThreadTest +import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation +import com.android.launcher3.AbstractFloatingView +import com.android.launcher3.AbstractFloatingView.TYPE_OPTIONS_POPUP +import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS +import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY +import com.android.launcher3.AbstractFloatingView.hasOpenView +import com.android.launcher3.taskbar.TaskbarActivityContext +import com.android.launcher3.taskbar.TaskbarUnitTestRule +import com.android.launcher3.taskbar.TaskbarUnitTestRule.InjectController +import com.android.launcher3.util.LauncherMultivalentJUnit +import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices +import com.android.systemui.shared.system.TaskStackChangeListeners +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(LauncherMultivalentJUnit::class) +@EmulatedDevices(["pixelFoldable2023"]) +class TaskbarOverlayControllerTest { + + @get:Rule val taskbarUnitTestRule = TaskbarUnitTestRule() + @InjectController lateinit var overlayController: TaskbarOverlayController + + private val taskbarContext: TaskbarActivityContext + get() = taskbarUnitTestRule.activityContext + + @Test + @UiThreadTest + fun testRequestWindow_twice_reusesWindow() { + val context1 = overlayController.requestWindow() + val context2 = overlayController.requestWindow() + assertThat(context1).isSameInstanceAs(context2) + } + + @Test + @UiThreadTest + fun testRequestWindow_afterHidingExistingWindow_createsNewWindow() { + val context1 = overlayController.requestWindow() + overlayController.hideWindow() + + val context2 = overlayController.requestWindow() + assertThat(context1).isNotSameInstanceAs(context2) + } + + @Test + @UiThreadTest + fun testRequestWindow_addsProxyView() { + TestOverlayView.show(overlayController.requestWindow()) + assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isTrue() + } + + @Test + @UiThreadTest + fun testRequestWindow_closeProxyView_closesOverlay() { + val overlay = TestOverlayView.show(overlayController.requestWindow()) + AbstractFloatingView.closeOpenContainer(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY) + assertThat(overlay.isOpen).isFalse() + } + + @Test + @UiThreadTest + fun testHideWindow_closesOverlay() { + val overlay = TestOverlayView.show(overlayController.requestWindow()) + overlayController.hideWindow() + assertThat(overlay.isOpen).isFalse() + } + + @Test + @UiThreadTest + fun testTwoOverlays_closeOne_windowStaysOpen() { + val context = overlayController.requestWindow() + val overlay1 = TestOverlayView.show(context) + val overlay2 = TestOverlayView.show(context) + + overlay1.close(false) + assertThat(overlay2.isOpen).isTrue() + assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isTrue() + } + + @Test + @UiThreadTest + fun testTwoOverlays_closeAll_closesWindow() { + val context = overlayController.requestWindow() + val overlay1 = TestOverlayView.show(context) + val overlay2 = TestOverlayView.show(context) + + overlay1.close(false) + overlay2.close(false) + assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isFalse() + } + + @Test + @UiThreadTest + fun testRecreateTaskbar_closesWindow() { + TestOverlayView.show(overlayController.requestWindow()) + taskbarUnitTestRule.recreateTaskbar() + assertThat(hasOpenView(taskbarContext, TYPE_TASKBAR_OVERLAY_PROXY)).isFalse() + } + + @Test + fun testTaskMovedToFront_closesOverlay() { + lateinit var overlay: TestOverlayView + getInstrumentation().runOnMainSync { + overlay = TestOverlayView.show(overlayController.requestWindow()) + } + + TaskStackChangeListeners.getInstance().listenerImpl.onTaskMovedToFront(RunningTaskInfo()) + // Make sure TaskStackChangeListeners' Handler posts the callback before checking state. + getInstrumentation().runOnMainSync { assertThat(overlay.isOpen).isFalse() } + } + + @Test + fun testTaskStackChanged_allAppsClosed_overlayStaysOpen() { + lateinit var overlay: TestOverlayView + getInstrumentation().runOnMainSync { + overlay = TestOverlayView.show(overlayController.requestWindow()) + taskbarContext.controllers.sharedState?.allAppsVisible = false + } + + TaskStackChangeListeners.getInstance().listenerImpl.onTaskStackChanged() + getInstrumentation().runOnMainSync { assertThat(overlay.isOpen).isTrue() } + } + + @Test + fun testTaskStackChanged_allAppsOpen_closesOverlay() { + lateinit var overlay: TestOverlayView + getInstrumentation().runOnMainSync { + overlay = TestOverlayView.show(overlayController.requestWindow()) + taskbarContext.controllers.sharedState?.allAppsVisible = true + } + + TaskStackChangeListeners.getInstance().listenerImpl.onTaskStackChanged() + getInstrumentation().runOnMainSync { assertThat(overlay.isOpen).isFalse() } + } + + @Test + @UiThreadTest + fun testUpdateLauncherDeviceProfile_overlayNotRebindSafe_closesOverlay() { + val overlayContext = overlayController.requestWindow() + val overlay = TestOverlayView.show(overlayContext).apply { type = TYPE_OPTIONS_POPUP } + + overlayController.updateLauncherDeviceProfile( + overlayController.launcherDeviceProfile + .toBuilder(overlayContext) + .setGestureMode(false) + .build() + ) + + assertThat(overlay.isOpen).isFalse() + } + + @Test + @UiThreadTest + fun testUpdateLauncherDeviceProfile_overlayRebindSafe_overlayStaysOpen() { + val overlayContext = overlayController.requestWindow() + val overlay = TestOverlayView.show(overlayContext).apply { type = TYPE_TASKBAR_ALL_APPS } + + overlayController.updateLauncherDeviceProfile( + overlayController.launcherDeviceProfile + .toBuilder(overlayContext) + .setGestureMode(false) + .build() + ) + + assertThat(overlay.isOpen).isTrue() + } + + private class TestOverlayView + private constructor( + private val overlayContext: TaskbarOverlayContext, + ) : AbstractFloatingView(overlayContext, null) { + + var type = TYPE_OPTIONS_POPUP + + private fun show() { + mIsOpen = true + overlayContext.dragLayer.addView(this) + } + + override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean = false + + override fun handleClose(animate: Boolean) = overlayContext.dragLayer.removeView(this) + + override fun isOfType(type: Int): Boolean = (type and this.type) != 0 + + companion object { + /** Adds a generic View to the Overlay window for testing. */ + fun show(context: TaskbarOverlayContext): TestOverlayView { + return TestOverlayView(context).apply { show() } + } + } + } +} From 11eaec69f47f98824c74df74b76ae15093fbc629 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 12 Jun 2024 11:02:56 -0400 Subject: [PATCH 110/143] Add debug logs to BaseOverview#isActionsViewVisible Flag: NONE debug logs Bug: 336660988 Test: TaplTestsQuickstep#testQuickSwitchFromHome Change-Id: If241cd732cfce83d4799895f5e43048d775d72ed --- .../android/launcher3/tapl/BaseOverview.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index 567a8bd1c0..27f6c1661e 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -45,7 +45,6 @@ import java.util.stream.Collectors; * Common overview panel for both Launcher and fallback recents */ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { - private static final String TAG = "BaseOverview"; protected static final String TASK_RES_ID = "task"; private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile( "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0"); @@ -385,32 +384,39 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { } protected boolean isActionsViewVisible() { - if (!hasTasks() || isClearAllVisible()) { - Log.d(TAG, "Not expecting an actions bar: no tasks/'Clear all' is visible"); + boolean hasTasks = hasTasks(); + if (!hasTasks || isClearAllVisible()) { + LauncherInstrumentation.log("Not expecting an actions bar:" + + (!hasTasks ? "no recent tasks" : "clear all button is visible")); return false; } boolean isTablet = mLauncher.isTablet(); if (isTablet && mLauncher.isGridOnlyOverviewEnabled()) { - Log.d(TAG, "Not expecting an actions bar: device is tablet with grid-only Overview"); + LauncherInstrumentation.log("Not expecting an actions bar: " + + "device is tablet with grid-only Overview"); return false; } OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask(); if (task == null) { - Log.d(TAG, "Not expecting an actions bar: no current task"); + LauncherInstrumentation.log("Not expecting an actions bar: no focused task"); return false; } + float centerOffset = Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()); // In tablets, if focused task is not in center, overview actions aren't visible. - if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) { - Log.d(TAG, "Not expecting an actions bar: device is tablet and task is not centered"); + if (isTablet && centerOffset >= 1) { + LauncherInstrumentation.log("Not expecting an actions bar: " + + "device is tablet and task is not centered; center offset by " + + centerOffset + "px"); return false; } if (task.isTaskSplit() && (!mLauncher.isAppPairsEnabled() || !isTablet)) { - Log.d(TAG, "Not expecting an actions bar: device is phone and task is split"); + LauncherInstrumentation.log("Not expecting an actions bar: " + + "device is phone and task is split"); // Overview actions aren't visible for split screen tasks, except for save app pair // button on tablets. return false; } - Log.d(TAG, "Expecting an actions bar"); + LauncherInstrumentation.log("Expecting an actions bar"); return true; } @@ -493,13 +499,18 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { throw new IllegalStateException("Must be run on tablet device."); } final List taskViews = getTasks(); - if (taskViews.size() == 0) { + if (!hasTasks()) { + LauncherInstrumentation.log("no recent tasks"); return null; } int focusedTaskHeight = mLauncher.getFocusedTaskHeightForTablet(); for (UiObject2 task : taskViews) { OverviewTask overviewTask = new OverviewTask(mLauncher, task, this); + LauncherInstrumentation.log("checking task height (" + + overviewTask.getVisibleHeight() + + ") against defined focused task height (" + + focusedTaskHeight + ")"); if (overviewTask.getVisibleHeight() == focusedTaskHeight) { return overviewTask; } From b8eb034271a878946054d65a3bf4f035b5bd7140 Mon Sep 17 00:00:00 2001 From: mpodolian Date: Wed, 12 Jun 2024 19:13:17 +0100 Subject: [PATCH 111/143] Add outline to the transient task bar background. Added outline to the transient task bar background. Demo: http://recall/-/gx8ASgewUeUS3QYohfrd1J/gmJKD6VAuGXP8KOP1vLwad Fixes: 330785041 Flag: NONE Trivial UI update Test: Manual. Open transient task bar with the light and the dark themes. Change-Id: I69db4b40a1bd101471c2a2556a0621ac4494b8ec --- .../taskbar/TaskbarBackgroundRenderer.kt | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt index bafd05924f..7144a38d7a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt @@ -37,8 +37,6 @@ import kotlin.math.min class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { private val isInSetup: Boolean = !context.isUserSetupComplete - private val DARK_THEME_SHADOW_ALPHA = 51f - private val LIGHT_THEME_SHADOW_ALPHA = 25f private val maxTransientTaskbarHeight = context.transientTaskbarDeviceProfile.taskbarHeight.toFloat() @@ -54,6 +52,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { var isAnimatingPinning = false val paint = Paint() + private val strokePaint = Paint() val lastDrawnTransientRect = RectF() var backgroundHeight = context.deviceProfile.taskbarHeight.toFloat() var translationYForSwipe = 0f @@ -62,6 +61,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { private val transientBackgroundBounds = context.transientTaskbarBounds private val shadowAlpha: Float + private val strokeAlpha: Int private var shadowBlur = 0f private var keyShadowDistance = 0f private var bottomMargin = 0 @@ -86,10 +86,18 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { paint.color = context.getColor(R.color.taskbar_background) paint.flags = Paint.ANTI_ALIAS_FLAG paint.style = Paint.Style.FILL - - shadowAlpha = - if (Utilities.isDarkTheme(context)) DARK_THEME_SHADOW_ALPHA - else LIGHT_THEME_SHADOW_ALPHA + strokePaint.color = context.getColor(R.color.taskbar_stroke) + strokePaint.flags = Paint.ANTI_ALIAS_FLAG + strokePaint.style = Paint.Style.STROKE + strokePaint.strokeWidth = + context.resources.getDimension(R.dimen.transient_taskbar_stroke_width) + if (Utilities.isDarkTheme(context)) { + strokeAlpha = DARK_THEME_STROKE_ALPHA + shadowAlpha = DARK_THEME_SHADOW_ALPHA + } else { + strokeAlpha = LIGHT_THEME_STROKE_ALPHA + shadowAlpha = LIGHT_THEME_SHADOW_ALPHA + } setCornerRoundness(DEFAULT_ROUNDNESS) } @@ -236,6 +244,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { keyShadowDistance, setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha)) ) + strokePaint.alpha = (paint.alpha * strokeAlpha) / 255 lastDrawnTransientRect.set( transientBackgroundBounds.left + halfWidthDelta, @@ -247,6 +256,7 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { lastDrawnTransientRect.inset(horizontalInset, 0f) canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, paint) + canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, strokePaint) } /** @@ -259,5 +269,9 @@ class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) { companion object { const val DEFAULT_ROUNDNESS = 1f + private const val DARK_THEME_STROKE_ALPHA = 51 + private const val LIGHT_THEME_STROKE_ALPHA = 41 + private const val DARK_THEME_SHADOW_ALPHA = 51f + private const val LIGHT_THEME_SHADOW_ALPHA = 25f } } From 6b234217ebb7a53adc6163f0c35ae11c9fd18c1d Mon Sep 17 00:00:00 2001 From: Saumya Prakash Date: Tue, 11 Jun 2024 20:58:13 +0000 Subject: [PATCH 112/143] Fix gesture tutorial regression on tablets when rotating the screen This change addresses a regression that would incorrectly show the rotation prompt in the gesture navigation tutorial on tablets. Fix: 339735651 Test: Run the gesture navigation tutorial in different types of devices and ensure the rotate device prompt only shows up when necessary (ex. portrait mode on a tablet). Flag: EXEMPT bugfix Change-Id: I82d90313917e4ffe478ee2babdc8dc0cb306504c --- .../interaction/GestureSandboxActivity.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java index 4f1dbbe87b..36ea9269b4 100644 --- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java @@ -59,6 +59,7 @@ public class GestureSandboxActivity extends FragmentActivity { @Nullable private TutorialType[] mTutorialSteps; private GestureSandboxFragment mCurrentFragment; + private GestureSandboxFragment mPendingFragment; private int mCurrentStep; private int mNumSteps; @@ -176,16 +177,26 @@ public class GestureSandboxActivity extends FragmentActivity { && getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; - showFragment(showRotationPrompt + GestureSandboxFragment fragment = showRotationPrompt ? new RotationPromptFragment() - : mCurrentFragment.canRecreateFragment() - ? mCurrentFragment.recreateFragment() : mCurrentFragment); + : mCurrentFragment.canRecreateFragment() || mPendingFragment == null + ? mCurrentFragment.recreateFragment() + : mPendingFragment.recreateFragment(); + showFragment(fragment == null ? mCurrentFragment : fragment); + } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } } private void showFragment(@NonNull GestureSandboxFragment fragment) { + // Store the current fragment in mPendingFragment so that it can be recreated after the + // new fragment is shown. + if (mCurrentFragment.canRecreateFragment()) { + mPendingFragment = mCurrentFragment; + } else { + mPendingFragment = null; + } mCurrentFragment = fragment; getSupportFragmentManager().beginTransaction() .replace(R.id.gesture_tutorial_fragment_container, mCurrentFragment) From a76fcaf5b4dde4bdf8f91c23cccd91d4d54cde85 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Wed, 12 Jun 2024 15:53:33 -0400 Subject: [PATCH 113/143] Add more tests for {request,hide}Window. Flag: TEST_ONLY Fix: 346394585 Test: TaskbarOverlayControllerTests Change-Id: I59ed58d7f3a4d46bccfb34ef6923f1bf4f5bf2c1 --- .../overlay/TaskbarOverlayControllerTest.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt index 8768cb974b..eebd8f9f16 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayControllerTest.kt @@ -30,6 +30,7 @@ import com.android.launcher3.taskbar.TaskbarUnitTestRule import com.android.launcher3.taskbar.TaskbarUnitTestRule.InjectController import com.android.launcher3.util.LauncherMultivalentJUnit import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices +import com.android.launcher3.views.BaseDragLayer import com.android.systemui.shared.system.TaskStackChangeListeners import com.google.common.truth.Truth.assertThat import org.junit.Rule @@ -64,6 +65,17 @@ class TaskbarOverlayControllerTest { assertThat(context1).isNotSameInstanceAs(context2) } + @Test + @UiThreadTest + fun testRequestWindow_afterHidingOverlay_createsNewWindow() { + val context1 = overlayController.requestWindow() + TestOverlayView.show(context1) + overlayController.hideWindow() + + val context2 = overlayController.requestWindow() + assertThat(context1).isNotSameInstanceAs(context2) + } + @Test @UiThreadTest fun testRequestWindow_addsProxyView() { @@ -79,6 +91,17 @@ class TaskbarOverlayControllerTest { assertThat(overlay.isOpen).isFalse() } + @Test + fun testRequestWindow_attachesDragLayer() { + lateinit var dragLayer: BaseDragLayer<*> + getInstrumentation().runOnMainSync { + dragLayer = overlayController.requestWindow().dragLayer + } + + // Allow drag layer to attach before checking. + getInstrumentation().runOnMainSync { assertThat(dragLayer.isAttachedToWindow).isTrue() } + } + @Test @UiThreadTest fun testHideWindow_closesOverlay() { @@ -87,6 +110,20 @@ class TaskbarOverlayControllerTest { assertThat(overlay.isOpen).isFalse() } + @Test + fun testHideWindow_detachesDragLayer() { + lateinit var dragLayer: BaseDragLayer<*> + getInstrumentation().runOnMainSync { + dragLayer = overlayController.requestWindow().dragLayer + } + + // Wait for drag layer to be attached to window before hiding. + getInstrumentation().runOnMainSync { + overlayController.hideWindow() + assertThat(dragLayer.isAttachedToWindow).isFalse() + } + } + @Test @UiThreadTest fun testTwoOverlays_closeOne_windowStaysOpen() { From e16fc827d3a50a35f1379e70c0ba44edfdac4c74 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Wed, 12 Jun 2024 16:21:35 -0400 Subject: [PATCH 114/143] Add more documentation explaining main thread requirements. Flag: TEST_ONLY Test: n/a Bug: 230027385 Change-Id: Iad38f946c2e75a3372253e57abb4df2f52e62ca5 --- .../launcher3/taskbar/TaskbarUnitTestRule.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt index 77cd1fe67a..a999e7f7de 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarUnitTestRule.kt @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar +import android.app.Instrumentation import android.app.PendingIntent import android.content.IIntentSender import android.content.Intent @@ -37,6 +38,25 @@ import org.junit.runners.model.Statement * Manages the Taskbar lifecycle for unit tests. * * See [InjectController] for grabbing controller(s) under test with minimal boilerplate. + * + * The rule interacts with [TaskbarManager] on the main thread. A good rule of thumb for tests is + * that code that is executed on the main thread in production should also happen on that thread + * when tested. + * + * `@UiThreadTest` is a simple way to run an entire test body on the main thread. But if a test + * executes code that appends message(s) to the main thread's `MessageQueue`, the annotation will + * prevent those messages from being processed until after the test body finishes. + * + * To test pending messages, instead use something like [Instrumentation.runOnMainSync] to perform + * only sections of the test body on the main thread synchronously: + * ``` + * @Test + * fun example() { + * instrumentation.runOnMainSync { doWorkThatPostsMessage() } + * // Second lambda will not execute until message is processed. + * instrumentation.runOnMainSync { verifyMessageResults() } + * } + * ``` */ class TaskbarUnitTestRule : MethodRule { private val instrumentation = InstrumentationRegistry.getInstrumentation() From d89f9a8e03ee10ac1c3e13daf7ea05d5a1c4a1c0 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Wed, 12 Jun 2024 22:16:36 +0000 Subject: [PATCH 115/143] [Launcher Jank] Avoid making ContentResolver binder calls from GestureNavigationSettingsObserver Test: manual Flag: NONE performance change Bug: 333772683 Change-Id: Id6764315d9a2de959186785d4406a6b671e449f5 --- .../com/android/launcher3/taskbar/TaskbarInsetsController.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 0b60e455b2..2103ebbd10 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -53,6 +53,7 @@ import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController import com.android.launcher3.testing.shared.ResourceUtils import com.android.launcher3.util.DisplayController +import com.android.launcher3.util.Executors import java.io.PrintWriter import kotlin.jvm.optionals.getOrNull import kotlin.math.max @@ -76,6 +77,7 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas private val gestureNavSettingsObserver = GestureNavigationSettingsObserver( context.mainThreadHandler, + Executors.UI_HELPER_EXECUTOR.handler, context, this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged ) From e54c1462a38a7bc7d1767c08e6dcdb358f4733f2 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Thu, 6 Jun 2024 18:26:16 -0400 Subject: [PATCH 116/143] Test TaskbarAllAppsController non-search behavior. Flag: TEST_ONLY Bug: 230027385, 346394798 Test: TaskbarAllAppsControllerTest Change-Id: Id97e1b82cb8fba48687b5e23222e3bba6695ac4c --- .../allapps/TaskbarAllAppsControllerTest.kt | 185 ++++++++++++++++++ .../notification/NotificationKeyData.java | 6 + 2 files changed, 191 insertions(+) create mode 100644 quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt new file mode 100644 index 0000000000..c09dcf27de --- /dev/null +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt @@ -0,0 +1,185 @@ +/* + * 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.taskbar.allapps + +import android.content.ComponentName +import android.content.Intent +import android.os.Process +import androidx.test.annotation.UiThreadTest +import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation +import com.android.launcher3.BubbleTextView +import com.android.launcher3.appprediction.PredictionRowView +import com.android.launcher3.model.data.AppInfo +import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.notification.NotificationKeyData +import com.android.launcher3.taskbar.TaskbarUnitTestRule +import com.android.launcher3.taskbar.TaskbarUnitTestRule.InjectController +import com.android.launcher3.taskbar.overlay.TaskbarOverlayController +import com.android.launcher3.util.LauncherMultivalentJUnit +import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices +import com.android.launcher3.util.PackageUserKey +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(LauncherMultivalentJUnit::class) +@EmulatedDevices(["pixelFoldable2023", "pixelTablet2023"]) +class TaskbarAllAppsControllerTest { + + @get:Rule val taskbarUnitTestRule = TaskbarUnitTestRule() + + @InjectController lateinit var allAppsController: TaskbarAllAppsController + @InjectController lateinit var overlayController: TaskbarOverlayController + + @Test + @UiThreadTest + fun testToggle_once_showsAllApps() { + allAppsController.toggle() + assertThat(allAppsController.isOpen).isTrue() + } + + @Test + @UiThreadTest + fun testToggle_twice_closesAllApps() { + allAppsController.toggle() + allAppsController.toggle() + assertThat(allAppsController.isOpen).isFalse() + } + + @Test + @UiThreadTest + fun testToggle_taskbarRecreated_allAppsReopened() { + allAppsController.toggle() + taskbarUnitTestRule.recreateTaskbar() + assertThat(allAppsController.isOpen).isTrue() + } + + @Test + @UiThreadTest + fun testSetApps_beforeOpened_cachesInfo() { + allAppsController.setApps(TEST_APPS, 0, emptyMap()) + allAppsController.toggle() + + val overlayContext = overlayController.requestWindow() + assertThat(overlayContext.appsView.appsStore.apps).isEqualTo(TEST_APPS) + } + + @Test + @UiThreadTest + fun testSetApps_afterOpened_updatesStore() { + allAppsController.toggle() + allAppsController.setApps(TEST_APPS, 0, emptyMap()) + + val overlayContext = overlayController.requestWindow() + assertThat(overlayContext.appsView.appsStore.apps).isEqualTo(TEST_APPS) + } + + @Test + @UiThreadTest + fun testSetPredictedApps_beforeOpened_cachesInfo() { + allAppsController.setPredictedApps(TEST_PREDICTED_APPS) + allAppsController.toggle() + + val predictedApps = + overlayController + .requestWindow() + .appsView + .floatingHeaderView + .findFixedRowByType(PredictionRowView::class.java) + .predictedApps + assertThat(predictedApps).isEqualTo(TEST_PREDICTED_APPS) + } + + @Test + @UiThreadTest + fun testSetPredictedApps_afterOpened_cachesInfo() { + allAppsController.toggle() + allAppsController.setPredictedApps(TEST_PREDICTED_APPS) + + val predictedApps = + overlayController + .requestWindow() + .appsView + .floatingHeaderView + .findFixedRowByType(PredictionRowView::class.java) + .predictedApps + assertThat(predictedApps).isEqualTo(TEST_PREDICTED_APPS) + } + + @Test + fun testUpdateNotificationDots_appInfo_hasDot() { + getInstrumentation().runOnMainSync { + allAppsController.setApps(TEST_APPS, 0, emptyMap()) + allAppsController.toggle() + taskbarUnitTestRule.activityContext.popupDataProvider.onNotificationPosted( + PackageUserKey.fromItemInfo(TEST_APPS[0]), + NotificationKeyData("key"), + ) + } + + // Ensure the recycler view fully inflates before trying to grab an icon. + getInstrumentation().runOnMainSync { + val btv = + overlayController + .requestWindow() + .appsView + .activeRecyclerView + .findViewHolderForAdapterPosition(0) + ?.itemView as? BubbleTextView + assertThat(btv?.hasDot()).isTrue() + } + } + + @Test + @UiThreadTest + fun testUpdateNotificationDots_predictedApp_hasDot() { + allAppsController.setPredictedApps(TEST_PREDICTED_APPS) + allAppsController.toggle() + + taskbarUnitTestRule.activityContext.popupDataProvider.onNotificationPosted( + PackageUserKey.fromItemInfo(TEST_PREDICTED_APPS[0]), + NotificationKeyData("key"), + ) + + val predictionRowView = + overlayController + .requestWindow() + .appsView + .floatingHeaderView + .findFixedRowByType(PredictionRowView::class.java) + val btv = predictionRowView.getChildAt(0) as BubbleTextView + assertThat(btv.hasDot()).isTrue() + } + + private companion object { + private val TEST_APPS = + Array(16) { + AppInfo( + ComponentName( + getInstrumentation().context, + "com.android.launcher3.tests.Activity$it", + ), + "Test App $it", + Process.myUserHandle(), + Intent(), + ) + } + + private val TEST_PREDICTED_APPS = TEST_APPS.take(4).map { WorkspaceItemInfo(it) } + } +} diff --git a/src/com/android/launcher3/notification/NotificationKeyData.java b/src/com/android/launcher3/notification/NotificationKeyData.java index 4115b3da5c..e38824cb4b 100644 --- a/src/com/android/launcher3/notification/NotificationKeyData.java +++ b/src/com/android/launcher3/notification/NotificationKeyData.java @@ -22,6 +22,7 @@ import android.service.notification.StatusBarNotification; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.Utilities; @@ -38,6 +39,11 @@ public class NotificationKeyData { public final String[] personKeysFromNotification; public int count; + @VisibleForTesting + public NotificationKeyData(String notificationKey) { + this(notificationKey, null, 1, new String[]{}); + } + private NotificationKeyData(String notificationKey, String shortcutId, int count, String[] personKeysFromNotification) { this.notificationKey = notificationKey; From 6d200f63ac3f71a896257e6cf77ca02a7c80a966 Mon Sep 17 00:00:00 2001 From: Sebastian Franco Date: Wed, 12 Jun 2024 19:39:49 -0600 Subject: [PATCH 117/143] If the app is archived, do not remove in case of playstore install error Fix: 339852615 Test: Manual Flag: com.android.launcher3.enable_support_for_archiving Change-Id: I675586d20d09f9e025dfe6a74cf7b79ddcb40cc2 --- src/com/android/launcher3/LauncherModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 47a71152e0..ca1b2a91f7 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -480,7 +480,7 @@ public class LauncherModel implements InstallSessionTracker.Callback { } } - if (!removedIds.isEmpty()) { + if (!removedIds.isEmpty() && !isAppArchived) { taskController.deleteAndBindComponentsRemoved( ItemInfoMatcher.ofItemIds(removedIds), "removed because install session failed"); From 3b7282e08c139714299347ed778b1c82d12baac9 Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Thu, 13 Jun 2024 11:20:06 +0200 Subject: [PATCH 118/143] Use ktfmt.sh wrapper for ktfmt hook This CL makes the ktfmt hook use the bash wrapper introduced in ag/I8746885396c7837a2a6b2a42dca780da290ed582 instead of directly executing the ktfmt.jar, now that gLinux is not able to execute JAR files directly anymore. Bug: 342153000 Test: Manual, verified that the ktfmt hook was working Flag: EXEMPT repo hook Change-Id: Ib3baec68951bb185e79638b5b3003f8403816b19 --- PREUPLOAD.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index ff97b22e4e..9051ca8562 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -5,7 +5,7 @@ ktfmt = true ktfmt = --kotlinlang-style [Tool Paths] -ktfmt = ${REPO_ROOT}/prebuilts/build-tools/common/framework/ktfmt.jar +ktfmt = ${REPO_ROOT}/external/ktfmt/ktfmt.sh [Hook Scripts] checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --config_xml tools/checkstyle.xml --sha ${PREUPLOAD_COMMIT} From 73c766d75df4138dfbfb184aadd7febf3a6adaad Mon Sep 17 00:00:00 2001 From: Sihua Ma Date: Wed, 12 Jun 2024 08:07:30 +0000 Subject: [PATCH 119/143] Migrate responsive tests to multivalent Test: atest NexusLauncherRoboTests Test: SysUI studio Flag: TEST_ONLY Fix: 325088640 Change-Id: I32cce09ff7ef070b6c86b6440723006b5cb503cf --- .../launcher3/AbstractDeviceProfileTest.kt | 7 +++- .../launcher3/responsive/AllAppsSpecsTest.kt | 9 ++--- .../responsive/CalculatedAllAppsSpecTest.kt | 5 +-- .../responsive/CalculatedFolderSpecTest.kt | 9 ++--- .../responsive/CalculatedHotseatSpecTest.kt | 7 ++-- .../responsive/CalculatedWorkspaceSpecTest.kt | 7 ++-- .../launcher3/responsive/FolderSpecTest.kt | 23 ++++++------ .../responsive/HotseatSpecsProviderTest.kt | 9 ++--- .../ResponsiveCellSpecsProviderTest.kt | 9 ++--- .../responsive/ResponsiveSpecsProviderTest.kt | 17 ++++----- .../responsive/WorkspaceSpecsTest.kt | 11 +++--- .../launcher3/util/TestResourceHelper.kt | 37 ++++++++++++++----- 12 files changed, 81 insertions(+), 69 deletions(-) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt (93%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt (95%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt (95%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt (95%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt (96%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/FolderSpecTest.kt (92%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt (93%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt (92%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt (93%) rename tests/{ => multivalentTests}/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt (94%) rename tests/{ => multivalentTests}/src/com/android/launcher3/util/TestResourceHelper.kt (51%) diff --git a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index 3405635426..8770859957 100644 --- a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -57,7 +57,7 @@ import org.mockito.kotlin.whenever * * For an implementation that mocks InvariantDeviceProfile, use [FakeInvariantDeviceProfileTest] */ -@AllowedDevices(allowed = [DeviceProduct.CF_PHONE, DeviceProduct.HOST_SIDE_X86_64]) +@AllowedDevices(allowed = [DeviceProduct.CF_PHONE, DeviceProduct.ROBOLECTRIC]) @IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD) abstract class AbstractDeviceProfileTest { protected val testContext: Context = InstrumentationRegistry.getInstrumentation().context @@ -341,4 +341,9 @@ abstract class AbstractDeviceProfileTest { protected fun Int.dpToPx(): Int { return ResourceUtils.pxFromDp(this.toFloat(), context!!.resources.displayMetrics) } + + protected fun String.xmlToId(): Int { + val context = InstrumentationRegistry.getInstrumentation().context + return context.resources.getIdentifier(this, "xml", context.packageName) + } } diff --git a/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt similarity index 93% rename from tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt index c99da96917..3dca35e383 100644 --- a/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -45,7 +44,7 @@ class AllAppsSpecsTest : AbstractDeviceProfileTest() { fun parseValidFile() { val allAppsSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_all_apps_file), + TestResourceHelper(context, "valid_all_apps_file".xmlToId()), ResponsiveSpecType.AllApps ) @@ -114,7 +113,7 @@ class AllAppsSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_missingTag_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_all_apps_file_case_1), + TestResourceHelper(context, "invalid_all_apps_file_case_1".xmlToId()), ResponsiveSpecType.AllApps ) } @@ -122,7 +121,7 @@ class AllAppsSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_moreThanOneValuePerTag_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_all_apps_file_case_2), + TestResourceHelper(context, "invalid_all_apps_file_case_2".xmlToId()), ResponsiveSpecType.AllApps ) } @@ -130,7 +129,7 @@ class AllAppsSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_valueBiggerThan1_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_all_apps_file_case_3), + TestResourceHelper(context, "invalid_all_apps_file_case_3".xmlToId()), ResponsiveSpecType.AllApps ) } diff --git a/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt similarity index 95% rename from tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt index 1cc5ed2500..8346492079 100644 --- a/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt @@ -23,7 +23,6 @@ import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType import com.android.launcher3.responsive.ResponsiveSpec.DimensionType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -52,7 +51,7 @@ class CalculatedAllAppsSpecTest : AbstractDeviceProfileTest() { val workspaceSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_workspace_file), + TestResourceHelper(context, "valid_workspace_file".xmlToId()), ResponsiveSpecType.Workspace ) val widthSpec = @@ -62,7 +61,7 @@ class CalculatedAllAppsSpecTest : AbstractDeviceProfileTest() { val allAppsSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_all_apps_file), + TestResourceHelper(context, "valid_all_apps_file".xmlToId()), ResponsiveSpecType.AllApps ) diff --git a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt similarity index 95% rename from tests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt index c4e2d2a328..46d6cb9304 100644 --- a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedFolderSpecTest.kt @@ -23,7 +23,6 @@ import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType import com.android.launcher3.responsive.ResponsiveSpec.DimensionType -import com.android.launcher3.tests.R import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -47,12 +46,12 @@ class CalculatedFolderSpecTest : AbstractDeviceProfileTest() { val columns = 6 // Loading workspace specs - val resourceHelperWorkspace = TestResourceHelper(context, R.xml.valid_workspace_file) + val resourceHelperWorkspace = TestResourceHelper(context, "valid_workspace_file".xmlToId()) val workspaceSpecs = ResponsiveSpecsProvider.create(resourceHelperWorkspace, ResponsiveSpecType.Workspace) // Loading folders specs - val resourceHelperFolder = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelperFolder = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelperFolder, ResponsiveSpecType.Folder) val specs = folderSpecs.getSpecsByAspectRatio(aspectRatio) @@ -123,12 +122,12 @@ class CalculatedFolderSpecTest : AbstractDeviceProfileTest() { val rows = 5 // Loading workspace specs - val resourceHelperWorkspace = TestResourceHelper(context, R.xml.valid_workspace_file) + val resourceHelperWorkspace = TestResourceHelper(context, "valid_workspace_file".xmlToId()) val workspaceSpecs = ResponsiveSpecsProvider.create(resourceHelperWorkspace, ResponsiveSpecType.Workspace) // Loading folders specs - val resourceHelperFolder = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelperFolder = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelperFolder, ResponsiveSpecType.Folder) val specs = folderSpecs.getSpecsByAspectRatio(aspectRatio) diff --git a/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt similarity index 95% rename from tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt index 1a564aced5..5ab44f350c 100644 --- a/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.DimensionType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -47,7 +46,7 @@ class CalculatedHotseatSpecTest : AbstractDeviceProfileTest() { val availableHeight = deviceSpec.naturalSize.second val hotseatSpecsProvider = - HotseatSpecsProvider.create(TestResourceHelper(context, TestR.xml.valid_hotseat_file)) + HotseatSpecsProvider.create(TestResourceHelper(context, "valid_hotseat_file".xmlToId())) val heightSpec = hotseatSpecsProvider.getCalculatedSpec( aspectRatio, @@ -73,7 +72,7 @@ class CalculatedHotseatSpecTest : AbstractDeviceProfileTest() { val availableHeight = deviceSpec.naturalSize.second val hotseatSpecsProvider = - HotseatSpecsProvider.create(TestResourceHelper(context, TestR.xml.valid_hotseat_file)) + HotseatSpecsProvider.create(TestResourceHelper(context, "valid_hotseat_file".xmlToId())) val heightSpec = hotseatSpecsProvider.getCalculatedSpec( aspectRatio, @@ -99,7 +98,7 @@ class CalculatedHotseatSpecTest : AbstractDeviceProfileTest() { val hotseatSpecsProvider = HotseatSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_hotseat_land_file) + TestResourceHelper(context, "valid_hotseat_land_file".xmlToId()) ) val widthSpec = hotseatSpecsProvider.getCalculatedSpec(aspectRatio, DimensionType.WIDTH, availableWidth) diff --git a/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt similarity index 96% rename from tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt index 0c5d347412..dea98b6f8b 100644 --- a/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt @@ -23,7 +23,6 @@ import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType import com.android.launcher3.responsive.ResponsiveSpec.DimensionType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -53,7 +52,7 @@ class CalculatedWorkspaceSpecTest : AbstractDeviceProfileTest() { val workspaceSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_workspace_file), + TestResourceHelper(context, "valid_workspace_file".xmlToId()), ResponsiveSpecType.Workspace ) val widthSpec = @@ -96,7 +95,7 @@ class CalculatedWorkspaceSpecTest : AbstractDeviceProfileTest() { val workspaceSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_workspace_file), + TestResourceHelper(context, "valid_workspace_file".xmlToId()), ResponsiveSpecType.Workspace ) val widthSpec = @@ -138,7 +137,7 @@ class CalculatedWorkspaceSpecTest : AbstractDeviceProfileTest() { val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 640 val workspaceSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_workspace_unsorted_file), + TestResourceHelper(context, "valid_workspace_unsorted_file".xmlToId()), ResponsiveSpecType.Workspace ) val widthSpec = diff --git a/tests/src/com/android/launcher3/responsive/FolderSpecTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/FolderSpecTest.kt similarity index 92% rename from tests/src/com/android/launcher3/responsive/FolderSpecTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/FolderSpecTest.kt index 5cfa49fb49..d2b264bf57 100644 --- a/tests/src/com/android/launcher3/responsive/FolderSpecTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/FolderSpecTest.kt @@ -23,7 +23,6 @@ import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType import com.android.launcher3.responsive.ResponsiveSpec.DimensionType -import com.android.launcher3.tests.R import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -44,7 +43,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { @Test fun parseValidFile() { - val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelper = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) val specs = folderSpecs.getSpecsByAspectRatio(aspectRatio) @@ -92,25 +91,25 @@ class FolderSpecTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_missingTag_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_1) + val resourceHelper = TestResourceHelper(context, "invalid_folders_specs_1".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_moreThanOneValuePerTag_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_2) + val resourceHelper = TestResourceHelper(context, "invalid_folders_specs_2".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_valueBiggerThan1_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_3) + val resourceHelper = TestResourceHelper(context, "invalid_folders_specs_3".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_missingSpecs_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_4) + val resourceHelper = TestResourceHelper(context, "invalid_folders_specs_4".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) } @@ -132,7 +131,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { val calculatedWorkspaceSpec = CalculatedResponsiveSpec(aspectRatio, availableSpace, cells, workspaceSpec) - val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_5) + val resourceHelper = TestResourceHelper(context, "invalid_folders_specs_5".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) folderSpecs.getCalculatedSpec( aspectRatio, @@ -161,7 +160,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { val calculatedWorkspaceSpec = CalculatedResponsiveSpec(aspectRatio, availableSpace, cells, workspaceSpec) - val resourceHelper = TestResourceHelper(context, R.xml.invalid_folders_specs_5) + val resourceHelper = TestResourceHelper(context, "invalid_folders_specs_5".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) folderSpecs.getCalculatedSpec( aspectRatio, @@ -190,7 +189,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { val calculatedWorkspaceSpec = CalculatedResponsiveSpec(aspectRatio, availableSpace, cells, workspaceSpec) - val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelper = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) val calculatedWidthSpec = folderSpecs.getCalculatedSpec( @@ -227,7 +226,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { val calculatedWorkspaceSpec = CalculatedResponsiveSpec(aspectRatio, availableSpace, cells, workspaceSpec) - val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelper = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) folderSpecs.getCalculatedSpec( aspectRatio, @@ -256,7 +255,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { val calculatedWorkspaceSpec = CalculatedResponsiveSpec(aspectRatio, availableSpace, cells, workspaceSpec) - val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelper = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) val calculatedHeightSpec = folderSpecs.getCalculatedSpec( @@ -293,7 +292,7 @@ class FolderSpecTest : AbstractDeviceProfileTest() { val calculatedWorkspaceSpec = CalculatedResponsiveSpec(aspectRatio, availableSpace, cells, workspaceSpec) - val resourceHelper = TestResourceHelper(context, R.xml.valid_folders_specs) + val resourceHelper = TestResourceHelper(context, "valid_folders_specs".xmlToId()) val folderSpecs = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Folder) folderSpecs.getCalculatedSpec( aspectRatio, diff --git a/tests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt similarity index 93% rename from tests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt index 78cb1ac3ef..58324e1e43 100644 --- a/tests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/HotseatSpecsProviderTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -44,7 +43,7 @@ class HotseatSpecsProviderTest : AbstractDeviceProfileTest() { @Test fun parseValidFile() { val hotseatSpecsProvider = - HotseatSpecsProvider.create(TestResourceHelper(context, TestR.xml.valid_hotseat_file)) + HotseatSpecsProvider.create(TestResourceHelper(context, "valid_hotseat_file".xmlToId())) val specs = hotseatSpecsProvider.getSpecsByAspectRatio(aspectRatio) val expectedHeightSpecs = @@ -76,7 +75,7 @@ class HotseatSpecsProviderTest : AbstractDeviceProfileTest() { fun parseValidLandscapeFile() { val hotseatSpecsProvider = HotseatSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_hotseat_land_file) + TestResourceHelper(context, "valid_hotseat_land_file".xmlToId()) ) val specs = hotseatSpecsProvider.getSpecsByAspectRatio(aspectRatio) assertThat(specs.heightSpecs.size).isEqualTo(0) @@ -107,14 +106,14 @@ class HotseatSpecsProviderTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_spaceIsNotFixedSize_throwsError() { HotseatSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_hotseat_file_case_1) + TestResourceHelper(context, "invalid_hotseat_file_case_1".xmlToId()) ) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_invalidFixedSize_throwsError() { HotseatSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_hotseat_file_case_2) + TestResourceHelper(context, "invalid_hotseat_file_case_2".xmlToId()) ) } } diff --git a/tests/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt similarity index 92% rename from tests/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt index 50cd358b7e..11161bd525 100644 --- a/tests/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/ResponsiveCellSpecsProviderTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -43,7 +42,7 @@ class ResponsiveCellSpecsProviderTest : AbstractDeviceProfileTest() { @Test fun parseValidFile() { - val testResourceHelper = TestResourceHelper(context, TestR.xml.valid_cell_specs_file) + val testResourceHelper = TestResourceHelper(context, "valid_cell_specs_file".xmlToId()) val provider = ResponsiveCellSpecsProvider.create(testResourceHelper) // Validate Portrait @@ -98,21 +97,21 @@ class ResponsiveCellSpecsProviderTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_IsNotFixedSizeOrMatchWorkspace_throwsError() { ResponsiveCellSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_cell_specs_1) + TestResourceHelper(context, "invalid_cell_specs_1".xmlToId()) ) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_dimensionTypeIsNotHeight_throwsError() { ResponsiveCellSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_cell_specs_2) + TestResourceHelper(context, "invalid_cell_specs_2".xmlToId()) ) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_invalidFixedSize_throwsError() { ResponsiveCellSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_cell_specs_3) + TestResourceHelper(context, "invalid_cell_specs_3".xmlToId()) ) } } diff --git a/tests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt similarity index 93% rename from tests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt index 54a1dc567f..c74f7a8ca0 100644 --- a/tests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/ResponsiveSpecsProviderTest.kt @@ -23,7 +23,6 @@ import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType import com.android.launcher3.responsive.ResponsiveSpec.DimensionType -import com.android.launcher3.tests.R import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -44,7 +43,7 @@ class ResponsiveSpecsProviderTest : AbstractDeviceProfileTest() { @Test fun parseValidFile() { - val resourceHelper = TestResourceHelper(context, R.xml.valid_responsive_spec_unsorted) + val resourceHelper = TestResourceHelper(context, "valid_responsive_spec_unsorted".xmlToId()) val provider = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) // Validate Portrait @@ -111,44 +110,44 @@ class ResponsiveSpecsProviderTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseValidFile_invalidAspectRatio_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.valid_responsive_spec_unsorted) + val resourceHelper = TestResourceHelper(context, "valid_responsive_spec_unsorted".xmlToId()) val provider = ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) provider.getSpecsByAspectRatio(0f) } @Test(expected = InvalidResponsiveGridSpec::class) fun parseInvalidFile_missingGroups_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_1) + val resourceHelper = TestResourceHelper(context, "invalid_responsive_spec_1".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) } @Test(expected = InvalidResponsiveGridSpec::class) fun parseInvalidFile_partialGroups_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_2) + val resourceHelper = TestResourceHelper(context, "invalid_responsive_spec_2".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_invalidAspectRatio_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_3) + val resourceHelper = TestResourceHelper(context, "invalid_responsive_spec_3".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_invalidRemainderSpace_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_4) + val resourceHelper = TestResourceHelper(context, "invalid_responsive_spec_4".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_invalidAvailableSpace_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_5) + val resourceHelper = TestResourceHelper(context, "invalid_responsive_spec_5".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) } @Test(expected = IllegalStateException::class) fun parseInvalidFile_invalidFixedSize_throwsError() { - val resourceHelper = TestResourceHelper(context, R.xml.invalid_responsive_spec_6) + val resourceHelper = TestResourceHelper(context, "invalid_responsive_spec_6".xmlToId()) ResponsiveSpecsProvider.create(resourceHelper, ResponsiveSpecType.Workspace) } diff --git a/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt b/tests/multivalentTests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt similarity index 94% rename from tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt rename to tests/multivalentTests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt index 17b0ee4020..bc133ba7bb 100644 --- a/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType -import com.android.launcher3.tests.R as TestR import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -45,7 +44,7 @@ class WorkspaceSpecsTest : AbstractDeviceProfileTest() { fun parseValidFile() { val workspaceSpecs = ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.valid_workspace_file), + TestResourceHelper(context, "valid_workspace_file".xmlToId()), ResponsiveSpecType.Workspace ) @@ -169,7 +168,7 @@ class WorkspaceSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_missingTag_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_1), + TestResourceHelper(context, "invalid_workspace_file_case_1".xmlToId()), ResponsiveSpecType.Workspace ) } @@ -177,7 +176,7 @@ class WorkspaceSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_moreThanOneValuePerTag_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_2), + TestResourceHelper(context, "invalid_workspace_file_case_2".xmlToId()), ResponsiveSpecType.Workspace ) } @@ -185,7 +184,7 @@ class WorkspaceSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_valueBiggerThan1_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_3), + TestResourceHelper(context, "invalid_workspace_file_case_3".xmlToId()), ResponsiveSpecType.Workspace ) } @@ -193,7 +192,7 @@ class WorkspaceSpecsTest : AbstractDeviceProfileTest() { @Test(expected = IllegalStateException::class) fun parseInvalidFile_matchWorkspace_true_throwsError() { ResponsiveSpecsProvider.create( - TestResourceHelper(context, TestR.xml.invalid_workspace_file_case_4), + TestResourceHelper(context, "invalid_workspace_file_case_4".xmlToId()), ResponsiveSpecType.Workspace ) } diff --git a/tests/src/com/android/launcher3/util/TestResourceHelper.kt b/tests/multivalentTests/src/com/android/launcher3/util/TestResourceHelper.kt similarity index 51% rename from tests/src/com/android/launcher3/util/TestResourceHelper.kt rename to tests/multivalentTests/src/com/android/launcher3/util/TestResourceHelper.kt index b4d3ba853a..d95c6f8b50 100644 --- a/tests/src/com/android/launcher3/util/TestResourceHelper.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/TestResourceHelper.kt @@ -19,24 +19,41 @@ package com.android.launcher3.util import android.content.Context import android.content.res.TypedArray import android.util.AttributeSet +import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import com.android.launcher3.R -import com.android.launcher3.tests.R as TestR import kotlin.IntArray class TestResourceHelper(private val context: Context, specsFileId: Int) : ResourceHelper(context, specsFileId) { + + val responsiveStyleables = listOf( + R.styleable.SizeSpec, + R.styleable.WorkspaceSpec, + R.styleable.FolderSpec, + R.styleable.AllAppsSpec, + R.styleable.ResponsiveSpecGroup + ) + override fun obtainStyledAttributes(attrs: AttributeSet, styleId: IntArray): TypedArray { val clone = - when { - styleId.contentEquals(R.styleable.SizeSpec) -> TestR.styleable.SizeSpec - styleId.contentEquals(R.styleable.WorkspaceSpec) -> TestR.styleable.WorkspaceSpec - styleId.contentEquals(R.styleable.FolderSpec) -> TestR.styleable.FolderSpec - styleId.contentEquals(R.styleable.AllAppsSpec) -> TestR.styleable.AllAppsSpec - styleId.contentEquals(R.styleable.ResponsiveSpecGroup) -> - TestR.styleable.ResponsiveSpecGroup - else -> styleId.clone() - } + if (responsiveStyleables.any { styleId.contentEquals(it) }) { + convertStyleId(styleId) + } else { + styleId.clone() + } return context.obtainStyledAttributes(attrs, clone) } + + private fun convertStyleId(styleableArr: IntArray): IntArray { + val targetContextRes = getInstrumentation().targetContext.resources + val context = getInstrumentation().context + return styleableArr + .map { attrId -> targetContextRes.getResourceName(attrId).split(":").last() } + .map { attrName -> + // Get required attr from context instead of targetContext + context.resources.getIdentifier(attrName, null, context.packageName) + } + .toIntArray() + } } From f953c122fc23ec82c33db7e57374768243dc7373 Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Tue, 11 Jun 2024 14:30:01 -0700 Subject: [PATCH 120/143] Use main executor directly In some tests runs mMainExector could be null, using it directly resolves this. Flag: com.android.wm.shell.enable_bubble_bar Test: treehugger Bug: 347010157 Change-Id: I05879da895739087971a5bfe920d8c1b190f0b44 --- .../launcher3/taskbar/bubbles/BubbleBarController.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java index 046f5b6afe..028df34c73 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java @@ -135,7 +135,6 @@ public class BubbleBarController extends IBubblesListener.Stub { private static final Executor BUBBLE_STATE_EXECUTOR = Executors.newSingleThreadExecutor( new SimpleThreadFactory("BubbleStateUpdates-", THREAD_PRIORITY_BACKGROUND)); - private final Executor mMainExecutor; private final LauncherApps mLauncherApps; private final BubbleIconFactory mIconFactory; private final SystemUiProxy mSystemUiProxy; @@ -198,7 +197,6 @@ public class BubbleBarController extends IBubblesListener.Stub { if (sBubbleBarEnabled) { mSystemUiProxy.setBubblesListener(this); } - mMainExecutor = MAIN_EXECUTOR; mLauncherApps = context.getSystemService(LauncherApps.class); mIconFactory = new BubbleIconFactory(context, context.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size), @@ -241,7 +239,7 @@ public class BubbleBarController extends IBubblesListener.Stub { private void createAndAddOverflowIfNeeded() { if (mOverflowBubble == null) { BubbleBarOverflow overflow = createOverflow(mContext); - mMainExecutor.execute(() -> { + MAIN_EXECUTOR.execute(() -> { // we're on the main executor now, so check that the overflow hasn't been created // again to avoid races. if (mOverflowBubble == null) { @@ -303,12 +301,12 @@ public class BubbleBarController extends IBubblesListener.Stub { } viewUpdate.currentBubbles = currentBubbles; } - mMainExecutor.execute(() -> applyViewChanges(viewUpdate)); + MAIN_EXECUTOR.execute(() -> applyViewChanges(viewUpdate)); }); } else { // No bubbles to load, immediately apply the changes. BUBBLE_STATE_EXECUTOR.execute( - () -> mMainExecutor.execute(() -> applyViewChanges(viewUpdate))); + () -> MAIN_EXECUTOR.execute(() -> applyViewChanges(viewUpdate))); } } @@ -496,7 +494,7 @@ public class BubbleBarController extends IBubblesListener.Stub { @Override public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { - mMainExecutor.execute( + MAIN_EXECUTOR.execute( () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation)); } From 1c794082a7b6eabd45533e34d49cac66554bc004 Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Tue, 11 Jun 2024 15:02:36 -0700 Subject: [PATCH 121/143] Fixing TaplUninstallRemoveTest#uninstallWorkspaceIcon Test: Presubmit Bug: 319501259 Flag: TEST_ONLY Change-Id: I69d64ac8a0a496c947acf7fdce142a37005aeedc --- tests/tapl/com/android/launcher3/tapl/Workspace.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index 4fa93ef2ca..9ac6768f42 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -444,6 +444,8 @@ public final class Workspace extends Home { Runnable expectLongClickEvents) { try (LauncherInstrumentation.Closable c = launcher.addContextLayer( "uninstalling app icon")) { + + final String appNameToUninstall = homeAppIcon.getAppName(); dragIconToWorkspace( launcher, homeAppIcon, @@ -468,7 +470,10 @@ public final class Workspace extends Home { try (LauncherInstrumentation.Closable c1 = launcher.addContextLayer( "uninstalled app by dragging to the drop bar")) { - return new Workspace(launcher); + final Workspace newWorkspace = new Workspace(launcher); + launcher.waitUntilLauncherObjectGone( + AppIcon.getAppIconSelector(appNameToUninstall)); + return newWorkspace; } } } From ac8e132f2da11bd0021bf0c6c36d24eb349c4d43 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Tue, 11 Jun 2024 15:52:55 -0400 Subject: [PATCH 122/143] Exclude home and recents activity types when overriding recents-excluded tasks These tasks could point to overview itself, causing a very confusing screenshot. By excluding these tasks, we will default to using the task preview Flag: NONE bug fix Fixes: 336334715 Test: used circle to search from home, swiped to home, then pressed "select" overview action button. also checked temp logs Change-Id: I0b0ca50585413b479e4830f06b57b8b5e19670a8 (cherry picked from commit 3eb4efac95571eb5837ca66cae840033fc5fd893) --- quickstep/src/com/android/quickstep/TopTaskTracker.java | 6 ++++-- .../src/com/android/quickstep/TouchInteractionService.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java index a2a6dde483..c8dd2417ec 100644 --- a/quickstep/src/com/android/quickstep/TopTaskTracker.java +++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java @@ -233,7 +233,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta * If the given task holds an activity that is excluded from recents, and there * is another running task that is not excluded from recents, returns that underlying task. */ - public @Nullable CachedTaskInfo otherVisibleTaskThisIsExcludedOver() { + public @Nullable CachedTaskInfo getVisibleNonExcludedTask() { if (mTopTask == null || (mTopTask.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) { // Not an excluded task. @@ -241,7 +241,9 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta } List visibleNonExcludedTasks = mAllCachedTasks.stream() .filter(t -> t.isVisible - && (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) + && (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0 + && t.getActivityType() != ACTIVITY_TYPE_HOME + && t.getActivityType() != ACTIVITY_TYPE_RECENTS) .toList(); return visibleNonExcludedTasks.isEmpty() ? null : new CachedTaskInfo(visibleNonExcludedTasks); diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 8cd733b51b..2abc81eddd 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -1162,7 +1162,7 @@ public class TouchInteractionService extends Service { // running activity as the task behind the overlay. TopTaskTracker.CachedTaskInfo otherVisibleTask = runningTask == null ? null - : runningTask.otherVisibleTaskThisIsExcludedOver(); + : runningTask.getVisibleNonExcludedTask(); if (otherVisibleTask != null) { ActiveGestureLog.INSTANCE.addLog(new CompoundString("Changing active task to ") .append(otherVisibleTask.getPackageName()) From 176ce85d27b18351edbe59f4bd54d4f0dd5a08f8 Mon Sep 17 00:00:00 2001 From: randypfohl Date: Wed, 8 May 2024 14:50:50 -0700 Subject: [PATCH 123/143] Abstracting StatefulActivity from StateManager Flag: NONE - abstraction with no logic changes. Test: Built and ran locally, for launcher3 and third party launchers Bug: 224595066 Change-Id: I9da15bdd649d3a20e98c6552bb9e9abaec72f97f --- .../DesktopRecentsTransitionController.kt | 4 +- .../uioverrides/QuickstepLauncher.java | 2 +- .../quickstep/FallbackActivityInterface.java | 3 +- .../quickstep/LauncherActivityInterface.java | 4 +- .../quickstep/OverviewCommandHelper.java | 5 +- .../android/quickstep/RecentsActivity.java | 11 ++- .../fallback/FallbackRecentsView.java | 2 +- .../AnimatorControllerWithResistance.java | 4 +- .../quickstep/util/OverviewToHomeAnim.java | 2 +- .../util/QuickstepOnboardingPrefs.java | 3 +- .../util/SplitAnimationController.kt | 6 +- .../quickstep/views/LauncherRecentsView.java | 3 +- .../android/quickstep/views/RecentsView.java | 5 +- src/com/android/launcher3/Launcher.java | 6 +- src/com/android/launcher3/LauncherState.java | 6 +- src/com/android/launcher3/Workspace.java | 2 +- .../allapps/LauncherAllAppsContainerView.java | 8 +- .../launcher3/statemanager/BaseState.java | 2 +- .../launcher3/statemanager/StateManager.java | 34 ++++---- .../statemanager/StatefulActivity.java | 37 ++------ .../statemanager/StatefulContainer.java | 84 +++++++++++++++++++ .../util/CannedAnimationCoordinator.kt | 7 +- 22 files changed, 160 insertions(+), 80 deletions(-) create mode 100644 src/com/android/launcher3/statemanager/StatefulContainer.java diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt index 0000c0db2c..9178062c2d 100644 --- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt +++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt @@ -35,7 +35,7 @@ import java.util.function.Consumer /** Manage recents related operations with desktop tasks */ class DesktopRecentsTransitionController( - private val stateManager: StateManager<*>, + private val stateManager: StateManager<*, *>, private val systemUiProxy: SystemUiProxy, private val appThread: IApplicationThread, private val depthController: DepthController? @@ -64,7 +64,7 @@ class DesktopRecentsTransitionController( private class RemoteDesktopLaunchTransitionRunner( private val desktopTaskView: DesktopTaskView, - private val stateManager: StateManager<*>, + private val stateManager: StateManager<*, *>, private val depthController: DepthController?, private val successCallback: Consumer? ) : RemoteTransitionStub() { diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index e3a2bab824..2168f7a318 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -1118,7 +1118,7 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer } @Override - protected void collectStateHandlers(List out) { + public void collectStateHandlers(List> out) { super.collectStateHandlers(out); out.add(getDepthController()); out.add(new RecentsViewStateController(this)); diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java index 9e896fddc5..89fbf4ad54 100644 --- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java +++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java @@ -154,7 +154,8 @@ public final class FallbackActivityInterface extends @Override public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { - final StateManager stateManager = getCreatedContainer().getStateManager(); + final StateManager stateManager = + getCreatedContainer().getStateManager(); if (stateManager.getState() == HOME) { exitRunnable.run(); notifyRecentsOfOrientation(deviceState); diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java index 08c2e1ca29..c42882714c 100644 --- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java @@ -36,6 +36,7 @@ import androidx.annotation.UiThread; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Flags; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherState; @@ -242,7 +243,8 @@ public final class LauncherActivityInterface extends @Override public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { - final StateManager stateManager = getCreatedContainer().getStateManager(); + final StateManager stateManager = + getCreatedContainer().getStateManager(); stateManager.addStateListener( new StateManager.StateListener() { @Override diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 26a7c2f5bf..7da92bce90 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -228,8 +228,9 @@ public class OverviewCommandHelper { } BaseActivityInterface activityInterface = mOverviewComponentObserver.getActivityInterface(); - RecentsView visibleRecentsView = activityInterface.getVisibleRecentsView(); - RecentsView createdRecentsView; + + RecentsView visibleRecentsView = activityInterface.getVisibleRecentsView(); + RecentsView createdRecentsView; Log.d(TAG, "executeCommand: " + cmd + " - visibleRecentsView: " + visibleRecentsView); diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 3df62dacae..13e98444f4 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -115,7 +115,7 @@ public final class RecentsActivity extends StatefulActivity implem private TISBindHelper mTISBindHelper; private @Nullable FallbackTaskbarUIController mTaskbarUIController; - private StateManager mStateManager; + private StateManager mStateManager; // Strong refs to runners which are cleared when the activity is destroyed private RemoteAnimationFactory mActivityLaunchAnimationRunner; @@ -386,6 +386,11 @@ public final class RecentsActivity extends StatefulActivity implem } } + @Override + public boolean shouldAnimateStateChange() { + return false; + } + /** * Initialize/update the device profile. */ @@ -462,12 +467,12 @@ public final class RecentsActivity extends StatefulActivity implem }; @Override - protected void collectStateHandlers(List out) { + public void collectStateHandlers(List> out) { out.add(new FallbackRecentsStateController(this)); } @Override - public StateManager getStateManager() { + public StateManager getStateManager() { return mStateManager; } diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 485d6c4391..f4a2738fef 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -93,7 +93,7 @@ public class FallbackRecentsView extends RecentsView getStateManager() { + public StateManager getStateManager() { return mContainer.getStateManager(); } diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java index c9647f596e..c7c04ed91c 100644 --- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java +++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java @@ -39,6 +39,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statemanager.StateManager; +import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.AllAppsSwipeController; import com.android.quickstep.DeviceConfigWrapper; @@ -163,7 +164,8 @@ public class AnimatorControllerWithResistance { recentsOrientedState.getContainerInterface().getCreatedContainer(); if (container != null) { RecentsView recentsView = container.getOverviewPanel(); - StateManager stateManager = recentsView.getStateManager(); + StateManager> stateManager = + recentsView.getStateManager(); if (stateManager.isInStableState(LauncherState.BACKGROUND_APP) && stateManager.isInTransition()) { diff --git a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java index 132d1c1390..492c8019ac 100644 --- a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java +++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java @@ -62,7 +62,7 @@ public class OverviewToHomeAnim { * {@link WorkspaceRevealAnim}. */ public void animateWithVelocity(float velocity) { - StateManager stateManager = mLauncher.getStateManager(); + StateManager stateManager = mLauncher.getStateManager(); LauncherState startState = stateManager.getState(); if (startState != OVERVIEW) { Log.e(TAG, "animateFromOverviewToHome: unexpected start state " + startState); diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java index 2a27dea744..cfe5b2cd61 100644 --- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java +++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java @@ -27,6 +27,7 @@ import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_COUNT; import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN; import static com.android.launcher3.util.OnboardingPrefs.HOTSEAT_DISCOVERY_TIP_COUNT; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; @@ -48,7 +49,7 @@ public class QuickstepOnboardingPrefs { * Sets up the initial onboarding behavior for the launcher */ public static void setup(QuickstepLauncher launcher) { - StateManager stateManager = launcher.getStateManager(); + StateManager stateManager = launcher.getStateManager(); if (!HOME_BOUNCE_SEEN.get(launcher)) { stateManager.addStateListener(new StateListener() { @Override diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt index 8243ededd2..d4b3576c36 100644 --- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt +++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt @@ -510,7 +510,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC apps: Array?, wallpapers: Array?, nonApps: Array?, - stateManager: StateManager<*>, + stateManager: StateManager<*, *>, depthController: DepthController?, info: TransitionInfo?, t: Transaction?, @@ -589,7 +589,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC @VisibleForTesting fun composeRecentsSplitLaunchAnimator( launchingTaskView: GroupedTaskView, - stateManager: StateManager<*>, + stateManager: StateManager<*, *>, depthController: DepthController?, info: TransitionInfo, t: Transaction, @@ -617,7 +617,7 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC apps: Array, wallpapers: Array, nonApps: Array, - stateManager: StateManager<*>, + stateManager: StateManager<*, *>, depthController: DepthController?, finishCallback: Runnable ) { diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 5284b44dde..e48a7c6053 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -37,6 +37,7 @@ import android.view.MotionEvent; import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.desktop.DesktopRecentsTransitionController; @@ -104,7 +105,7 @@ public class LauncherRecentsView extends RecentsView getStateManager() { + public StateManager getStateManager() { return mContainer.getStateManager(); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 9096b75eaa..ff8d7cf324 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -152,6 +152,7 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StateManager; +import com.android.launcher3.statemanager.StatefulContainer; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.touch.OverScroll; @@ -2487,7 +2488,9 @@ public abstract class RecentsView getStateManager(); + /** Returns the state manager used in RecentsView **/ + public abstract StateManager> getStateManager(); public void reset() { setCurrentTask(-1); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 6c9d4c06ce..4e566abddc 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -312,7 +312,7 @@ public class Launcher extends StatefulActivity private static boolean sIsNewProcess = true; - private StateManager mStateManager; + private StateManager mStateManager; private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500; @@ -2775,7 +2775,7 @@ public class Launcher extends StatefulActivity } @Override - protected void collectStateHandlers(List out) { + public void collectStateHandlers(List> out) { out.add(getAllAppsController()); out.add(getWorkspace()); } @@ -2996,7 +2996,7 @@ public class Launcher extends StatefulActivity } @Override - public StateManager getStateManager() { + public StateManager getStateManager() { return mStateManager; } diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index d2d56f2d8c..102189b530 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -440,7 +440,7 @@ public abstract class LauncherState implements BaseState { */ public void onBackInvoked(Launcher launcher) { if (this != NORMAL) { - StateManager lsm = launcher.getStateManager(); + StateManager lsm = launcher.getStateManager(); LauncherState lastState = lsm.getLastState(); lsm.goToState(lastState, forEndCallback(this::onBackAnimationCompleted)); } @@ -461,7 +461,7 @@ public abstract class LauncherState implements BaseState { */ public void onBackProgressed( Launcher launcher, @FloatRange(from = 0.0, to = 1.0) float backProgress) { - StateManager lsm = launcher.getStateManager(); + StateManager lsm = launcher.getStateManager(); LauncherState toState = lsm.getLastState(); lsm.onBackProgressed(toState, backProgress); } @@ -471,7 +471,7 @@ public abstract class LauncherState implements BaseState { * predictive back gesture. */ public void onBackCancelled(Launcher launcher) { - StateManager lsm = launcher.getStateManager(); + StateManager lsm = launcher.getStateManager(); LauncherState toState = lsm.getLastState(); lsm.onBackCancelled(toState); } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 584d08924f..e601a3e298 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -526,7 +526,7 @@ public class Workspace extends PagedView } updateChildrenLayersEnabled(); - StateManager stateManager = mLauncher.getStateManager(); + StateManager stateManager = mLauncher.getStateManager(); stateManager.addStateListener(new StateManager.StateListener() { @Override public void onStateTransitionComplete(LauncherState finalState) { diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java index 63a168e4e3..1e0f2892d6 100644 --- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java @@ -56,7 +56,7 @@ public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView manager = launcher.getStateManager(); + StateManager manager = launcher.getStateManager(); if (manager.isInTransition() && manager.getTargetState() != null) { return manager.getTargetState().shouldFloatingSearchBarUsePillWhenUnfocused(launcher); } @@ -70,7 +70,7 @@ public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView stateManager = launcher.getStateManager(); + StateManager stateManager = launcher.getStateManager(); // We want to rest at the current state's resting position, unless we are in transition and // the target state's resting position is higher (that way if we are closing the keyboard, @@ -95,7 +95,7 @@ public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView stateManager = mActivityContext.getStateManager(); + StateManager stateManager = mActivityContext.getStateManager(); // Special case to not expand the search bar when exiting All Apps on phones. if (stateManager.getCurrentStableState() == LauncherState.ALL_APPS @@ -117,7 +117,7 @@ public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView stateManager = mActivityContext.getStateManager(); + StateManager stateManager = mActivityContext.getStateManager(); // Special case to not expand the search bar when exiting All Apps on phones. if (stateManager.getCurrentStableState() == LauncherState.ALL_APPS diff --git a/src/com/android/launcher3/statemanager/BaseState.java b/src/com/android/launcher3/statemanager/BaseState.java index a01d402c43..b81729a712 100644 --- a/src/com/android/launcher3/statemanager/BaseState.java +++ b/src/com/android/launcher3/statemanager/BaseState.java @@ -21,7 +21,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.views.ActivityContext; /** - * Interface representing a state of a StatefulActivity + * Interface representing a state of a StatefulContainer */ public interface BaseState { diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java index eea1a7d5e9..ac07c0f2cf 100644 --- a/src/com/android/launcher3/statemanager/StateManager.java +++ b/src/com/android/launcher3/statemanager/StateManager.java @@ -26,6 +26,7 @@ import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; +import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -47,8 +48,11 @@ import java.util.stream.Collectors; /** * Class to manage transitions between different states for a StatefulActivity based on different * states + * @param STATE_TYPE Basestate used by the state manager + * @param STATEFUL_CONTAINER container object used to manage state */ -public class StateManager> { +public class StateManager, + STATEFUL_CONTAINER extends Context & StatefulContainer> { public static final String TAG = "StateManager"; // b/279059025, b/325463989 @@ -56,7 +60,7 @@ public class StateManager> { private final AnimationState mConfig = new AnimationState(); private final Handler mUiHandler; - private final StatefulActivity mActivity; + private final STATEFUL_CONTAINER mStatefulContainer; private final ArrayList> mListeners = new ArrayList<>(); private final STATE_TYPE mBaseState; @@ -71,12 +75,12 @@ public class StateManager> { private STATE_TYPE mRestState; - public StateManager(StatefulActivity l, STATE_TYPE baseState) { + public StateManager(STATEFUL_CONTAINER container, STATE_TYPE baseState) { mUiHandler = new Handler(Looper.getMainLooper()); - mActivity = l; + mStatefulContainer = container; mBaseState = baseState; mState = mLastStableState = mCurrentStableState = baseState; - mAtomicAnimationFactory = l.createAtomicAnimationFactory(); + mAtomicAnimationFactory = container.createAtomicAnimationFactory(); } public STATE_TYPE getState() { @@ -109,10 +113,10 @@ public class StateManager> { writer.println(prefix + "\tisInTransition:" + isInTransition()); } - public StateHandler[] getStateHandlers() { + public StateHandler[] getStateHandlers() { if (mStateHandlers == null) { - ArrayList handlers = new ArrayList<>(); - mActivity.collectStateHandlers(handlers); + ArrayList> handlers = new ArrayList<>(); + mStatefulContainer.collectStateHandlers(handlers); mStateHandlers = handlers.toArray(new StateHandler[handlers.size()]); } return mStateHandlers; @@ -130,7 +134,7 @@ public class StateManager> { * Returns true if the state changes should be animated. */ public boolean shouldAnimateStateChange() { - return !mActivity.isForceInvisible() && mActivity.isStarted(); + return mStatefulContainer.shouldAnimateStateChange(); } /** @@ -245,7 +249,7 @@ public class StateManager> { } animated &= areAnimatorsEnabled(); - if (mActivity.isInState(state)) { + if (mStatefulContainer.isInState(state)) { if (mConfig.currentAnimation == null) { // Run any queued runnable if (listener != null) { @@ -302,8 +306,8 @@ public class StateManager> { // Since state mBaseState can be reached from multiple states, just assume that the // transition plays in reverse and use the same duration as previous state. mConfig.duration = state == mBaseState - ? fromState.getTransitionDuration(mActivity, false /* isToState */) - : state.getTransitionDuration(mActivity, true /* isToState */); + ? fromState.getTransitionDuration(mStatefulContainer, false /* isToState */) + : state.getTransitionDuration(mStatefulContainer, true /* isToState */); prepareForAtomicAnimation(fromState, state, mConfig); AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).buildAnim(); if (listener != null) { @@ -336,7 +340,7 @@ public class StateManager> { PendingAnimation builder = new PendingAnimation(config.duration); prepareForAtomicAnimation(fromState, toState, config); - for (StateHandler handler : mActivity.getStateManager().getStateHandlers()) { + for (StateHandler handler : mStatefulContainer.getStateManager().getStateHandlers()) { handler.setStateWithAnimation(toState, config, builder); } return builder.buildAnim(); @@ -402,7 +406,7 @@ public class StateManager> { private void onStateTransitionStart(STATE_TYPE state) { mState = state; - mActivity.onStateSetStart(mState); + mStatefulContainer.onStateSetStart(mState); if (DEBUG) { Log.d(TAG, "onStateTransitionStart - state: " + state); @@ -419,7 +423,7 @@ public class StateManager> { mCurrentStableState = state; } - mActivity.onStateSetEnd(state); + mStatefulContainer.onStateSetEnd(state); if (state == mBaseState) { setRestState(null); } diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java index 30ba703fd7..28f2def8ab 100644 --- a/src/com/android/launcher3/statemanager/StatefulActivity.java +++ b/src/com/android/launcher3/statemanager/StatefulActivity.java @@ -18,7 +18,6 @@ package com.android.launcher3.statemanager; import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; -import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS; import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE; import android.content.res.Configuration; @@ -29,11 +28,9 @@ import android.view.View; import androidx.annotation.CallSuper; -import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.LauncherRootView; import com.android.launcher3.Utilities; -import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.util.window.WindowManagerProxy; import com.android.launcher3.views.BaseDragLayer; @@ -45,7 +42,7 @@ import java.util.List; * @param Type of state object */ public abstract class StatefulActivity> - extends BaseDraggingActivity { + extends BaseDraggingActivity implements StatefulContainer { public final Handler mHandler = new Handler(); private final Runnable mHandleDeferredResume = this::handleDeferredResume; @@ -67,19 +64,9 @@ public abstract class StatefulActivity> /** * Create handlers to control the property changes for this activity */ - protected abstract void collectStateHandlers(List out); - /** - * Returns true if the activity is in the provided state - */ - public boolean isInState(STATE_TYPE state) { - return getStateManager().getState() == state; - } - - /** - * Returns the state manager for this activity - */ - public abstract StateManager getStateManager(); + @Override + public abstract void collectStateHandlers(List> out); protected void inflateRootView(int layoutId) { mRootView = (LauncherRootView) LayoutInflater.from(this).inflate(layoutId, null); @@ -106,22 +93,12 @@ public abstract class StatefulActivity> if (mDeferredResumePending) { handleDeferredResume(); } - - if (state.hasFlag(FLAG_CLOSE_POPUPS)) { - AbstractFloatingView.closeAllOpenViews(this, !state.hasFlag(FLAG_NON_INTERACTIVE)); - } + StatefulContainer.super.onStateSetStart(state); } - /** - * Called when transition to state ends - */ - public void onStateSetEnd(STATE_TYPE state) { } - - /** - * Creates a factory for atomic state animations - */ - public AtomicAnimationFactory createAtomicAnimationFactory() { - return new AtomicAnimationFactory(0); + @Override + public boolean shouldAnimateStateChange() { + return !isForceInvisible() && isStarted(); } @Override diff --git a/src/com/android/launcher3/statemanager/StatefulContainer.java b/src/com/android/launcher3/statemanager/StatefulContainer.java new file mode 100644 index 0000000000..0cf0a27685 --- /dev/null +++ b/src/com/android/launcher3/statemanager/StatefulContainer.java @@ -0,0 +1,84 @@ +/* + * 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.statemanager; + + +import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS; +import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE; + +import androidx.annotation.CallSuper; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.views.ActivityContext; + +import java.util.List; + +/** + * Interface for a container that can be managed by a state manager. + * + * @param The type of state that the container can be in. + */ +public interface StatefulContainer> extends + ActivityContext { + + /** + * Creates a factory for atomic state animations + */ + default StateManager.AtomicAnimationFactory createAtomicAnimationFactory() { + return new StateManager.AtomicAnimationFactory<>(0); + } + + /** + * Create handlers to control the property changes for this activity + */ + void collectStateHandlers(List> out); + + /** + * Retrieves state manager for given container + */ + StateManager getStateManager(); + + /** + * Called when transition to state ends + * @param state current state of State_Type + */ + default void onStateSetEnd(STATE_TYPE state) { } + + /** + * Called when transition to state starts + * @param state current state of State_Type + */ + @CallSuper + default void onStateSetStart(STATE_TYPE state) { + if (state.hasFlag(FLAG_CLOSE_POPUPS)) { + AbstractFloatingView.closeAllOpenViews(this, !state.hasFlag(FLAG_NON_INTERACTIVE)); + } + } + + /** + * Returns true if the activity is in the provided state + * @param state current state of State_Type + */ + default boolean isInState(STATE_TYPE state) { + return getStateManager().getState() == state; + } + + /** + * Returns true if state change should transition with animation + */ + boolean shouldAnimateStateChange(); +} diff --git a/src/com/android/launcher3/util/CannedAnimationCoordinator.kt b/src/com/android/launcher3/util/CannedAnimationCoordinator.kt index 85f81f57ba..749caacd96 100644 --- a/src/com/android/launcher3/util/CannedAnimationCoordinator.kt +++ b/src/com/android/launcher3/util/CannedAnimationCoordinator.kt @@ -113,10 +113,9 @@ class CannedAnimationCoordinator(private val activity: StatefulActivity<*>) { // flags accordingly animationController = controller.apply { - activity.stateManager.setCurrentAnimation( - this, - USER_CONTROLLED or HANDLE_STATE_APPLY - ) + activity + .stateManager + .setCurrentAnimation(this, USER_CONTROLLED or HANDLE_STATE_APPLY) } recreateAnimation(provider) } From 4b409653464fa6fc446b06a8d9b4a73dc67ef2fa Mon Sep 17 00:00:00 2001 From: randypfohl Date: Fri, 10 May 2024 08:45:56 -0700 Subject: [PATCH 124/143] Fixing tests related to abstraction Flag: NONE - fixing tests Test: built and ran locally, verified test pass in presubmit Bug: 224595066 Change-Id: Ifefab1e1696853c5bd816a361314082073ba8a20 --- .../com/android/quickstep/util/SplitAnimationControllerTest.kt | 2 +- .../android/quickstep/util/SplitSelectStateControllerTest.kt | 3 ++- .../launcher3/taskbar/FallbackTaskbarUIControllerTest.kt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt index 250dc7b924..d40f8ab389 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt @@ -78,7 +78,7 @@ class SplitAnimationControllerTest { private val mockSplitSourceDrawable: Drawable = mock() private val mockSplitSourceView: View = mock() - private val stateManager: StateManager<*> = mock() + private val stateManager: StateManager<*, *> = mock() private val depthController: DepthController = mock() private val transitionInfo: TransitionInfo = mock() private val transaction: Transaction = mock() diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt index aa08ca4c05..bab84ef28b 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt @@ -31,6 +31,7 @@ import com.android.launcher3.logging.StatsLogManager.StatsLogger import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.statehandlers.DepthController import com.android.launcher3.statemanager.StateManager +import com.android.launcher3.statemanager.StatefulActivity import com.android.launcher3.util.ComponentKey import com.android.launcher3.util.SplitConfigurationOptions import com.android.quickstep.RecentsModel @@ -61,7 +62,7 @@ class SplitSelectStateControllerTest { private val depthController: DepthController = mock() private val statsLogManager: StatsLogManager = mock() private val statsLogger: StatsLogger = mock() - private val stateManager: StateManager = mock() + private val stateManager: StateManager> = mock() private val handler: Handler = mock() private val context: RecentsViewContainer = mock() private val recentsModel: RecentsModel = mock() diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt index f3115c6a52..04012c027d 100644 --- a/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt +++ b/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt @@ -37,7 +37,7 @@ class FallbackTaskbarUIControllerTest : TaskbarBaseTestCase() { lateinit var stateListener: StateManager.StateListener private val recentsActivity: RecentsActivity = mock() - private val stateManager: StateManager = mock() + private val stateManager: StateManager = mock() @Before override fun setup() { From f46de7e6908c8e118c99d9912e649f311b7b3763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Franco?= Date: Thu, 13 Jun 2024 18:43:21 +0000 Subject: [PATCH 125/143] Revert "Make sure we keep the screen record even if the test succeeds" This reverts commit ad15dd719ee50d57a9000cd6ceabfb8a63dd3773. Reason for revert: removing debug Change-Id: Id76a5b9a2e138603e896cba2a0d9b96711610f9e --- .../launcher3/ui/TaplTestsLauncher3Test.java | 4 +--- .../android/launcher3/ui/TaplWorkProfileTest.java | 2 -- .../launcher3/util/rule/ScreenRecordRule.java | 15 +-------------- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java index 4a67600024..342eedf2be 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java @@ -21,9 +21,8 @@ import static org.junit.Assert.assertNotNull; import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; -import com.android.launcher3.Launcher; -import com.android.launcher3.util.rule.ScreenRecordRule.KeepRecordOnSuccess; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; +import com.android.launcher3.Launcher; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,7 +31,6 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class TaplTestsLauncher3Test extends AbstractLauncherUiTest { - @KeepRecordOnSuccess @ScreenRecord // b/322823478 @Test public void testDevicePressMenu() throws Exception { diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java index 70a3dd001a..e08d37cb69 100644 --- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java +++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java @@ -45,7 +45,6 @@ import com.android.launcher3.allapps.WorkPausedCard; import com.android.launcher3.allapps.WorkProfileManager; import com.android.launcher3.tapl.LauncherInstrumentation; import com.android.launcher3.util.TestUtil; -import com.android.launcher3.util.rule.ScreenRecordRule.KeepRecordOnSuccess; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; import com.android.launcher3.util.rule.TestStabilityRule.Stability; @@ -197,7 +196,6 @@ public class TaplWorkProfileTest extends AbstractLauncherUiTest { } - @KeepRecordOnSuccess @ScreenRecord // b/322823478 @Test public void testEdu() { diff --git a/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java b/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java index ff96afb51d..7a5cf2c2cd 100644 --- a/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java +++ b/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java @@ -49,9 +49,6 @@ public class ScreenRecordRule implements TestRule { return base; } - final Boolean keepRecordOnSuccess = description.getAnnotation(KeepRecordOnSuccess.class) - != null; - return new Statement() { @Override public void evaluate() throws Throwable { @@ -73,7 +70,7 @@ public class ScreenRecordRule implements TestRule { device.executeShellCommand("kill -INT " + screenRecordPid); Log.e(TAG, "Screenrecord captured at: " + outputFile); output.close(); - if (success && !keepRecordOnSuccess) { + if (success) { automation.executeShellCommand("rm " + outputFile); } } @@ -88,14 +85,4 @@ public class ScreenRecordRule implements TestRule { @Target(ElementType.METHOD) public @interface ScreenRecord { } - - - /** - * Interface to indicate that we should keep the screen record even if the test succeeds, use - * sparingly since it uses a lof of memory. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - public @interface KeepRecordOnSuccess { - } } From 3cddb5817dfa3956514384a8ca3ccc81215c38bd Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Thu, 16 May 2024 14:39:38 -0700 Subject: [PATCH 126/143] Util classes for the Taskbar Customization Framework Test: Presubmit Bug: 341146605 Flag: NONE Taskbar Customization Change-Id: Ice9d2e6db2754ba75a1253da45dd28aa63cad58f --- .../taskbar/TaskbarRecentAppsController.kt | 7 +- .../taskbar/customization/TaskbarContainer.kt | 27 +++++ .../customization/TaskbarFeatureEvaluator.kt | 44 +++++++++ .../taskbar/customization/TaskbarIconSpecs.kt | 41 ++++++++ .../customization/TaskbarSpecsEvaluator.kt | 60 +++++++++++ .../TaskbarSpecsEvaluatorTest.kt | 99 +++++++++++++++++++ 6 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt create mode 100644 quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt create mode 100644 quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt create mode 100644 quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt create mode 100644 quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt index 0946caf986..b1fc9ccb02 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt @@ -46,8 +46,11 @@ class TaskbarRecentAppsController( enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps() // TODO(b/343532825): Add a setting to disable Recents even when the flag is on. - @VisibleForTesting - var isEnabled = enableRecentsInTaskbar() || canShowRunningApps + var isEnabled: Boolean = enableRecentsInTaskbar() || canShowRunningApps + @VisibleForTesting + set(isEnabledFromTest){ + field = isEnabledFromTest + } // Initialized in init. private lateinit var controllers: TaskbarControllers diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt new file mode 100644 index 0000000000..3c4b63a1d7 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt @@ -0,0 +1,27 @@ +/* + * 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.taskbar.customization + +/** Enums for all feature container that taskbar supports. */ +enum class TaskbarContainer { + ALL_APPS, + DIVIDER, + APP_ICONS, + RECENTS, + NAV_BUTTONS, + BUBBLES, +} diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt new file mode 100644 index 0000000000..1ec075ffaa --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt @@ -0,0 +1,44 @@ +/* + * 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.taskbar.customization + +import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning +import com.android.launcher3.taskbar.TaskbarActivityContext +import com.android.launcher3.taskbar.TaskbarControllers +import com.android.launcher3.taskbar.TaskbarRecentAppsController +import com.android.launcher3.util.DisplayController + +/** Evaluates all the features taskbar can have. */ +class TaskbarFeatureEvaluator( + private val taskbarActivityContext: TaskbarActivityContext, + private val taskbarControllers: TaskbarControllers, +) { + + val hasAllApps = true + val hasAppIcons = true + val hasBubbles = false + val hasNavButtons = taskbarActivityContext.isThreeButtonNav + + val hasRecents: Boolean + get() = taskbarControllers.taskbarRecentAppsController.isEnabled + + val hasDivider: Boolean + get() = enableTaskbarPinning() || hasRecents + + val isTransient: Boolean + get() = DisplayController.isTransientTaskbar(taskbarActivityContext) +} diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt new file mode 100644 index 0000000000..4cd895de4d --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt @@ -0,0 +1,41 @@ +/* + * 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.taskbar.customization + +/** Taskbar Icon Specs */ +object TaskbarIconSpecs { + + val iconSize40dp = TaskbarIconSize(40) + val iconSize44dp = TaskbarIconSize(44) + val iconSize48dp = TaskbarIconSize(48) + val iconSize52dp = TaskbarIconSize(52) + + val transientTaskbarIconSizes = arrayOf(iconSize44dp, iconSize48dp, iconSize52dp) + + val defaultPersistentIconSize = iconSize40dp + val defaultTransientIconSize = iconSize44dp + + // defined as row, columns + val transientTaskbarIconSizeByGridSize = + mapOf( + Pair(6, 5) to iconSize52dp, + Pair(4, 5) to iconSize48dp, + Pair(5, 4) to iconSize48dp, + Pair(4, 4) to iconSize48dp, + Pair(5, 6) to iconSize44dp, + ) +} diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt new file mode 100644 index 0000000000..02e5947b32 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt @@ -0,0 +1,60 @@ +/* + * 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.taskbar.customization + +/** Evaluates the taskbar specs based on the taskbar grid size and the taskbar icon size. */ +class TaskbarSpecsEvaluator(private val taskbarFeatureEvaluator: TaskbarFeatureEvaluator) { + + fun getIconSizeByGrid(row: Int, column: Int): TaskbarIconSize { + return if (taskbarFeatureEvaluator.isTransient) { + TaskbarIconSpecs.transientTaskbarIconSizeByGridSize.getOrDefault( + Pair(row, column), + TaskbarIconSpecs.defaultTransientIconSize, + ) + } else { + TaskbarIconSpecs.defaultPersistentIconSize + } + } + + fun getIconSizeStepDown(iconSize: TaskbarIconSize): TaskbarIconSize { + if (!taskbarFeatureEvaluator.isTransient) return TaskbarIconSpecs.defaultPersistentIconSize + + val currentIconSizeIndex = TaskbarIconSpecs.transientTaskbarIconSizes.indexOf(iconSize) + // return the current icon size if supplied icon size is unknown or we have reached the + // min icon size. + return if (currentIconSizeIndex == -1 || currentIconSizeIndex == 0) iconSize + else TaskbarIconSpecs.transientTaskbarIconSizes[currentIconSizeIndex - 1] + } + + fun getIconSizeStepUp(iconSize: TaskbarIconSize): TaskbarIconSize { + if (!taskbarFeatureEvaluator.isTransient) return TaskbarIconSpecs.defaultPersistentIconSize + + val currentIconSizeIndex = TaskbarIconSpecs.transientTaskbarIconSizes.indexOf(iconSize) + // return the current icon size if supplied icon size is unknown or we have reached the + // max icon size. + return if ( + currentIconSizeIndex == -1 || + currentIconSizeIndex == TaskbarIconSpecs.transientTaskbarIconSizes.size - 1 + ) { + iconSize + } else { + TaskbarIconSpecs.transientTaskbarIconSizes.get(currentIconSizeIndex + 1) + } + } +} + +data class TaskbarIconSize(val size: Int) diff --git a/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt b/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt new file mode 100644 index 0000000000..b637e7d4cf --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt @@ -0,0 +1,99 @@ +/* + * 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.quickstep.taskbar.customization + +import com.android.launcher3.taskbar.customization.TaskbarFeatureEvaluator +import com.android.launcher3.taskbar.customization.TaskbarIconSpecs +import com.android.launcher3.taskbar.customization.TaskbarSpecsEvaluator +import com.android.launcher3.util.LauncherMultivalentJUnit +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.whenever + +@RunWith(LauncherMultivalentJUnit::class) +class TaskbarSpecsEvaluatorTest { + + private val taskbarFeatureEvaluator = mock() + private val taskbarSpecsEvaluator = spy(TaskbarSpecsEvaluator(taskbarFeatureEvaluator)) + + @Test + fun testGetIconSizeByGrid_whenTaskbarIsTransient_withValidRowAndColumn() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(6, 5)) + .isEqualTo(TaskbarIconSpecs.iconSize52dp) + } + + @Test + fun testGetIconSizeByGrid_whenTaskbarIsTransient_withInvalidRowAndColumn() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(1, 2)) + .isEqualTo(TaskbarIconSpecs.defaultTransientIconSize) + } + + @Test + fun testGetIconSizeByGrid_whenTaskbarIsPersistent() { + doReturn(false).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(6, 5)) + .isEqualTo(TaskbarIconSpecs.defaultPersistentIconSize) + } + + @Test + fun testGetIconSizeStepDown_whenTaskbarIsPersistent() { + doReturn(false).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeStepDown(TaskbarIconSpecs.iconSize44dp)) + .isEqualTo(TaskbarIconSpecs.defaultPersistentIconSize) + } + + @Test + fun testGetIconSizeStepDown_whenTaskbarIsTransientAndIconSizeAreInBound() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeStepDown(TaskbarIconSpecs.iconSize52dp)) + .isEqualTo(TaskbarIconSpecs.iconSize48dp) + } + + @Test + fun testGetIconSizeStepDown_whenTaskbarIsTransientAndIconSizeAreOutOfBound() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeStepDown(TaskbarIconSpecs.iconSize44dp)) + .isEqualTo(TaskbarIconSpecs.iconSize44dp) + } + + @Test + fun testGetIconSizeStepUp_whenTaskbarIsPersistent() { + doReturn(false).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeStepUp(TaskbarIconSpecs.iconSize40dp)) + .isEqualTo(TaskbarIconSpecs.iconSize40dp) + } + + @Test + fun testGetIconSizeStepUp_whenTaskbarIsTransientAndIconSizeAreInBound() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeStepUp(TaskbarIconSpecs.iconSize44dp)) + .isEqualTo(TaskbarIconSpecs.iconSize48dp) + } + + @Test + fun testGetIconSizeStepUp_whenTaskbarIsTransientAndIconSizeAreOutOfBound() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + assertThat(taskbarSpecsEvaluator.getIconSizeStepUp(TaskbarIconSpecs.iconSize52dp)) + .isEqualTo(TaskbarIconSpecs.iconSize52dp) + } +} From fa1f4c9f79bfceca06a01b385aef751305b82a32 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Wed, 12 Jun 2024 19:56:43 -0400 Subject: [PATCH 127/143] Add test for toggleSearch. Focus is not requested until the open animation finishes, so we need to emulate the animation completing. Test: TaskbarAllAppsControllerTest Flag: TEST_ONLY Fix: 346394798 Change-Id: I5ba57e9bb1813c159599b31404a28ef10c85e3ee --- .../allapps/TaskbarAllAppsControllerTest.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt index c09dcf27de..fe4e2d2f70 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsControllerTest.kt @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar.allapps +import android.animation.AnimatorTestRule import android.content.ComponentName import android.content.Intent import android.os.Process @@ -42,6 +43,7 @@ import org.junit.runner.RunWith class TaskbarAllAppsControllerTest { @get:Rule val taskbarUnitTestRule = TaskbarUnitTestRule() + @get:Rule val animatorTestRule = AnimatorTestRule(this) @InjectController lateinit var allAppsController: TaskbarAllAppsController @InjectController lateinit var overlayController: TaskbarOverlayController @@ -166,6 +168,21 @@ class TaskbarAllAppsControllerTest { assertThat(btv.hasDot()).isTrue() } + @Test + fun testToggleSearch_searchEditTextFocused() { + getInstrumentation().runOnMainSync { allAppsController.toggleSearch() } + getInstrumentation().runOnMainSync { + // All Apps is now attached to window. Open animation is posted but not started. + } + + getInstrumentation().runOnMainSync { + // Animation has started. Advance to end of animation. + animatorTestRule.advanceTimeBy(overlayController.openDuration.toLong()) + } + val editText = overlayController.requestWindow().appsView.searchUiManager.editText + assertThat(editText?.hasFocus()).isTrue() + } + private companion object { private val TEST_APPS = Array(16) { From 1894a36cc8fabc09e67ec504b3b0ed755fb44200 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 13 Jun 2024 14:12:31 -0700 Subject: [PATCH 128/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Iaa31d82696378d6f2fa021b53e72628efa57cebc --- res/values-af/strings.xml | 2 ++ res/values-am/strings.xml | 2 ++ res/values-ar/strings.xml | 2 ++ res/values-as/strings.xml | 2 ++ res/values-az/strings.xml | 2 ++ res/values-b+sr+Latn/strings.xml | 2 ++ res/values-be/strings.xml | 2 ++ res/values-bg/strings.xml | 2 ++ res/values-bn/strings.xml | 2 ++ res/values-bs/strings.xml | 2 ++ res/values-ca/strings.xml | 2 ++ res/values-cs/strings.xml | 4 +++- res/values-da/strings.xml | 2 ++ res/values-de/strings.xml | 2 ++ res/values-el/strings.xml | 2 ++ res/values-en-rAU/strings.xml | 2 ++ res/values-en-rCA/strings.xml | 2 ++ res/values-en-rGB/strings.xml | 2 ++ res/values-en-rIN/strings.xml | 2 ++ res/values-en-rXC/strings.xml | 2 ++ res/values-es-rUS/strings.xml | 2 ++ res/values-es/strings.xml | 2 ++ res/values-et/strings.xml | 2 ++ res/values-eu/strings.xml | 2 ++ res/values-fa/strings.xml | 2 ++ res/values-fi/strings.xml | 2 ++ res/values-fr-rCA/strings.xml | 2 ++ res/values-fr/strings.xml | 2 ++ res/values-gl/strings.xml | 2 ++ res/values-gu/strings.xml | 2 ++ res/values-hi/strings.xml | 4 +++- res/values-hr/strings.xml | 4 +++- res/values-hu/strings.xml | 2 ++ res/values-hy/strings.xml | 2 ++ res/values-in/strings.xml | 2 ++ res/values-is/strings.xml | 2 ++ res/values-it/strings.xml | 2 ++ res/values-iw/strings.xml | 2 ++ res/values-ja/strings.xml | 2 ++ res/values-ka/strings.xml | 2 ++ res/values-kk/strings.xml | 4 +++- res/values-km/strings.xml | 2 ++ res/values-kn/strings.xml | 6 ++++-- res/values-ko/strings.xml | 2 ++ res/values-ky/strings.xml | 2 ++ res/values-lo/strings.xml | 2 ++ res/values-lt/strings.xml | 2 ++ res/values-lv/strings.xml | 2 ++ res/values-mk/strings.xml | 2 ++ res/values-ml/strings.xml | 2 ++ res/values-mn/strings.xml | 2 ++ res/values-mr/strings.xml | 2 ++ res/values-ms/strings.xml | 2 ++ res/values-my/strings.xml | 2 ++ res/values-nb/strings.xml | 2 ++ res/values-ne/strings.xml | 2 ++ res/values-nl/strings.xml | 2 ++ res/values-or/strings.xml | 2 ++ res/values-pa/strings.xml | 2 ++ res/values-pl/strings.xml | 2 ++ res/values-pt-rPT/strings.xml | 4 +++- res/values-pt/strings.xml | 2 ++ res/values-ro/strings.xml | 2 ++ res/values-ru/strings.xml | 2 ++ res/values-si/strings.xml | 2 ++ res/values-sk/strings.xml | 2 ++ res/values-sl/strings.xml | 2 ++ res/values-sq/strings.xml | 2 ++ res/values-sr/strings.xml | 2 ++ res/values-sv/strings.xml | 2 ++ res/values-sw/strings.xml | 2 ++ res/values-ta/strings.xml | 4 +++- res/values-te/strings.xml | 2 ++ res/values-th/strings.xml | 2 ++ res/values-tl/strings.xml | 2 ++ res/values-tr/strings.xml | 2 ++ res/values-uk/strings.xml | 2 ++ res/values-ur/strings.xml | 2 ++ res/values-uz/strings.xml | 2 ++ res/values-vi/strings.xml | 2 ++ res/values-zh-rCN/strings.xml | 2 ++ res/values-zh-rHK/strings.xml | 2 ++ res/values-zh-rTW/strings.xml | 4 +++- res/values-zu/strings.xml | 2 ++ 84 files changed, 177 insertions(+), 9 deletions(-) diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index ba507212a4..90e784dda9 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -27,6 +27,8 @@ "Legstukke gedeaktiveer in Veiligmodus" "Kortpad is nie beskikbaar nie" "Tuis" + + "Verdeelde skerm" "Programinligting vir %1$s" "Gebruikinstellings vir %1$s" diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index 10d68aa0f1..1289b8c591 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -27,6 +27,8 @@ "ምግብሮች በደህንነቱ የተጠበቀ ሁኔታ ተሰናክለዋል" "አቋራጭ አይገኝም" "መነሻ" + + "የተከፈለ ማያ ገፅ" "የመተግበሪያ መረጃ ለ%1$s" "የ%1$s የአጠቃቀም ቅንብሮች" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 6ba2ce6085..37d6fba70f 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -27,6 +27,8 @@ "الأدوات غير مفعّلة في الوضع الآمن" "الاختصار غير متاح" "الشاشة الرئيسية" + + "تقسيم الشاشة" "‏معلومات تطبيق %1$s" "‏إعدادات استخدام \"%1$s\"" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index ce86039da1..e983ce8a28 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -27,6 +27,8 @@ "ৱিজেটবোৰক সুৰক্ষিত ম\'ডত অক্ষম কৰা হ’ল" "শ্বৰ্টকাট নাই" "গৃহ স্ক্ৰীন" + + "বিভাজিত স্ক্ৰীন" "%1$sৰ বাবে এপৰ তথ্য" "%1$sৰ বাবে ব্যৱহাৰৰ ছেটিং" diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 9ad053a2f7..f390c7c260 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -27,6 +27,8 @@ "Vidcetlər Güvənli rejimdə deaktiv edilib" "Qısayol əlçatan deyil" "Əsas səhifə" + + "Ekran bölünməsi" "%1$s ilə bağlı tətbiq məlumatı" "%1$s üzrə istifadə ayarları" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 408a4258b8..fc71eeb76e 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -27,6 +27,8 @@ "Vidžeti su onemogućeni u Bezbednom režimu" "Prečica nije dostupna" "Početni ekran" + + "Podeljeni ekran" "Informacije o aplikaciji za: %1$s" "Podešavanja potrošnje za %1$s" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index c7ed9d926d..4589125b46 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -27,6 +27,8 @@ "Віджэты адключаны ў Бяспечным рэжыме" "Ярлык недаступны" "Галоўны экран" + + "Падзелены экран" "Інфармацыя пра праграму для: %1$s" "%1$s: налады выкарыстання" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index ce62054c02..643c24e5d6 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -27,6 +27,8 @@ "Приспособленията са деактивирани в безопасния режим" "Няма достъп до прекия път" "Начален екран" + + "Разделен екран" "Информация за приложението за %1$s" "Настройки за използването на %1$s" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index a9f4585215..7e10a0eaf1 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -27,6 +27,8 @@ "সুরক্ষিত মোডে উইজেট নিষ্ক্রিয় থাকে" "শর্টকাটগুলি অনুপলব্ধ" "হোম" + + "স্প্লিট স্ক্রিন" "%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য" "%1$s-এর জন্য ব্যবহারের সেটিংস" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 325d65d006..10aa86a871 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -27,6 +27,8 @@ "Vidžeti su onemogućeni u sigurnom načinu rada." "Prečica nije dostupna" "Početni ekran" + + "Podijeljeni ekran" "Informacije o aplikaciji %1$s" "Postavke korištenja za: %1$s" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 50ded7ba8b..3d2ff4a3d2 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -27,6 +27,8 @@ "En Mode segur, els widgets estan desactivats." "La drecera no està disponible" "Inici" + + "Pantalla dividida" "Informació de l\'aplicació %1$s" "Configuració d\'ús de %1$s" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index c570ef13fa..14a35836d9 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -27,6 +27,8 @@ "V nouzovém režimu jsou widgety zakázány." "Zkratka není k dispozici" "Domů" + + "Rozdělit obrazovku" "Informace o aplikaci %1$s" "Nastavení využití pro aplikaci %1$s" @@ -192,6 +194,6 @@ "Soukromé, uzamčeno." "Zamknout" "Převádění soukromého prostoru" - "Instalovat" + "Nainstalovat" "Instalovat aplikace do soukromého prostoru" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index e6f741f6e9..f18e1e8f03 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -27,6 +27,8 @@ "Widgets er deaktiveret i Beskyttet tilstand" "Genvejen er ikke tilgængelig" "Startskærm" + + "Opdel skærm" "Appinfo for %1$s" "Indstillinger for brug af %1$s" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 7f8924644e..9a4e5e2a30 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -27,6 +27,8 @@ "Widgets im abgesicherten Modus deaktiviert" "Verknüpfung nicht verfügbar" "Startbildschirm" + + "Splitscreen" "App-Info für %1$s" "Nutzungseinstellungen für %1$s" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 8ace970859..840ff5b3b1 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -27,6 +27,8 @@ "Τα γραφικά στοιχεία απενεργοποιήθηκαν στην ασφαλή λειτουργία" "Η συντόμευση δεν είναι διαθέσιμη" "Αρχική οθόνη" + + "Διαχωρισμός οθόνης" "Πληροφορίες εφαρμογής για %1$s" "Ρυθμίσεις χρήσης για %1$s" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 3fe69cd5b7..4deacb6b9d 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -27,6 +27,8 @@ "Widgets disabled in Safe mode" "Shortcut isn\'t available" "Home" + + "Split screen" "App info for %1$s" "Usage settings for %1$s" diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index dee4a30029..e9f951b491 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -27,6 +27,8 @@ "Widgets disabled in Safe mode" "Shortcut isn\'t available" "Home" + + "Split screen" "App info for %1$s" "Usage settings for %1$s" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 3fe69cd5b7..4deacb6b9d 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -27,6 +27,8 @@ "Widgets disabled in Safe mode" "Shortcut isn\'t available" "Home" + + "Split screen" "App info for %1$s" "Usage settings for %1$s" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 3fe69cd5b7..4deacb6b9d 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -27,6 +27,8 @@ "Widgets disabled in Safe mode" "Shortcut isn\'t available" "Home" + + "Split screen" "App info for %1$s" "Usage settings for %1$s" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index 69added946..fb08c7e581 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -27,6 +27,8 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎Widgets disabled in Safe mode‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎Shortcut isn\'t available‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎Home‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎Split screen‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎App info for %1$s‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎Usage settings for %1$s‎‏‎‎‏‎" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 75b697930f..e734744314 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -27,6 +27,8 @@ "Widgets inhabilitados en modo seguro" "El acceso directo no está disponible" "Pantalla principal" + + "Pantalla dividida" "Información de la app de %1$s" "Configuración del uso de %1$s" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 91e05a76b4..3e0e51645c 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -27,6 +27,8 @@ "Widgets inhabilitados en modo Seguro" "Acceso directo no disponible" "Inicio" + + "Pantalla dividida" "Información de la aplicación %1$s" "Ajustes de uso para %1$s" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 4ad9c9e13e..bab7da3bc8 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -27,6 +27,8 @@ "Turvarežiimis on vidinad keelatud" "Otsetee pole saadaval" "Avakuva" + + "Jagatud ekraanikuva" "Rakenduse teave: %1$s" "Kasutuse seaded: %1$s" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 8e68ebdc5a..b8017d6fee 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -27,6 +27,8 @@ "Widgetak desgaitu egin dira modu seguruan" "Lasterbideak ez daude erabilgarri" "Orri nagusia" + + "Pantaila zatitzea" "%1$s aplikazioari buruzko informazioa" "%1$s aplikazioaren erabilera-ezarpenak" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index a19134090a..b39945b759 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -27,6 +27,8 @@ "ابزارک‌ها در حالت ایمن غیرفعال هستند" "میان‌بر دردسترس نیست" "صفحه اصلی" + + "صفحهٔ دونیمه" "‏اطلاعات برنامه %1$s" "‏تنظیمات مصرف برای %1$s" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 00880b026d..181c89eaca 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -27,6 +27,8 @@ "Widgetit poistettu käytöstä vikasietotilassa" "Pikakuvake ei ole käytettävissä." "Etusivu" + + "Jaettu näyttö" "Sovellustiedot: %1$s" "Käyttöasetus tälle: %1$s" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index daa4b5fb94..f3b08cbdba 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -27,6 +27,8 @@ "Widgets désactivés en mode sans échec" "Le raccourci n\'est pas disponible" "Accueil" + + "Écran divisé" "Renseignements sur l\'appli pour %1$s" "Paramètres d\'utilisation pour %1$s" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 580d02f03c..4a7c7fb6d9 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -27,6 +27,8 @@ "Les widgets sont désactivés en mode sécurisé." "Raccourci non disponible" "Accueil" + + "Écran partagé" "Infos sur l\'appli pour %1$s" "Paramètres d\'utilisation pour %1$s" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index fc667bc91a..0430a9a680 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -27,6 +27,8 @@ "Os widgets están desactivados no modo seguro" "O atallo non está dispoñible" "Inicio" + + "Pantalla dividida" "Información da aplicación para %1$s" "Configuración de uso para %1$s" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index ce411e62db..3c248dbb95 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -27,6 +27,8 @@ "સુરક્ષિત મોડમાં વિજેટ્સ અક્ષમ કર્યા" "શૉર્ટકટ ઉપલબ્ધ નથી" "હોમ સ્ક્રીન" + + "સ્ક્રીનને વિભાજિત કરો" "%1$s માટે ઍપ માહિતી" "%1$sના વપરાશ સંબંધિત સેટિંગ" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index f1117ba6c8..50d4762ff6 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -27,6 +27,8 @@ "विजेट सुरक्षित मोड में अक्षम हैं" "शॉर्टकट उपलब्ध नहीं है" "होम स्क्रीन" + + "स्प्लिट स्क्रीन" "%1$s के लिए ऐप्लिकेशन की जानकारी" "%1$s के लिए खर्च की सेटिंग" @@ -88,7 +90,7 @@ "ऐप्लिकेशन अनइंस्टॉल करें" "इंस्‍टॉल करें" "ऐप्लिकेशन का सुझाव न दें" - "सुझाए गए ऐप्लिकेशन को पिन करें" + "सुझाए गए ऐप पिन करें" "शॉर्टकट इंस्‍टॉल करें" "ऐप को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देती है." "होम स्क्रीन की सेटिंग और शॉर्टकट पढ़ने की अनुमति" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 9d6049524c..7a1fd94cac 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -27,6 +27,8 @@ "Widgeti su onemogućeni u Sigurnom načinu rada" "Prečac nije dostupan" "Početni zaslon" + + "Podijeljeni zaslon" "Informacije o aplikaciji %1$s" "Postavke upotrebe za %1$s" @@ -192,6 +194,6 @@ "Privatno, zaključano." "Zaključavanje" "Prelazak na privatni prostor" - "Instaliraj" + "Instalirajte" "Instaliranje aplikacija u privatni prostor" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index bb39c3374c..3b556da7ef 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -27,6 +27,8 @@ "A modulok ki vannak kapcsolva Csökkentett módban" "A gyorsparancs nem áll rendelkezésre" "Kezdőképernyő" + + "Osztott képernyő" "Alkalmazásinformáció a következőhöz: %1$s" "A(z) %1$s használati beállításai" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 63b935d80a..491ba05be8 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -27,6 +27,8 @@ "Վիջեթներն անջատված են անվտանգ ռեժիմում" "Դյուրանցումն անհասանելի է" "Հիմնական էկրան" + + "Տրոհել էկրանը" "Տեղեկություններ %1$s հավելվածի մասին" "Օգտագործման կարգավորումներ (%1$s)" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index ca30b42e94..13353851b3 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -27,6 +27,8 @@ "Widget dinonaktifkan dalam mode Aman" "Pintasan tidak tersedia" "Layar utama" + + "Layar terpisah" "Info aplikasi untuk %1$s" "Setelan penggunaan untuk %1$s" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index aadb75ed93..48652642e0 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -27,6 +27,8 @@ "Græjur eru óvirkar í öruggri stillingu" "Flýtileið er ekki tiltæk" "Heim" + + "Skipta skjá" "Upplýsingar um forrit fyrir %1$s" "Notkunarstillingar fyrir %1$s" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 36950b84f3..41b4b609fa 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -27,6 +27,8 @@ "Widget disabilitati in modalità provvisoria" "La scorciatoia non è disponibile" "Home" + + "Schermo diviso" "Informazioni sull\'app %1$s" "Impostazioni di utilizzo per %1$s" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index e00e851fa9..ae71edd4e5 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -27,6 +27,8 @@ "ווידג\'טים מושבתים במצב בטוח" "קיצור הדרך אינו זמין" "בית" + + "מסך מפוצל" "‏פרטים על האפליקציה %1$s" "‏הגדרות שימוש ב-%1$s" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 1f8a93fc1c..c64d3352b5 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -27,6 +27,8 @@ "セーフモードではウィジェットは無効です" "ショートカットは使用できません" "ホーム" + + "分割画面" "%1$s のアプリ情報" "%1$s の使用設定" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index eac12be501..bcced9a3ff 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -27,6 +27,8 @@ "უსაფრთხო რეჟიმში ვიჯეტი გამორთულია" "მალსახმობი მიუწვდომელია" "მთავარი გვერდი" + + "ეკრანის გაყოფა" "%1$s-ის აპის ინფო" "გამოყენების პარამეტრები %1$s-ისთვის" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 383a50785b..62bb983b79 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -27,6 +27,8 @@ "Қауіпсіз режимде виджеттер өшіріледі" "Таңбаша қолжетімді емес" "Негізгі экран" + + "Экранды бөлу" "%1$s қолданбасы туралы ақпарат" "%1$s пайдалану параметрлері" @@ -88,7 +90,7 @@ "Қолданбаны жою" "Орнату" "Қолданба ұсынбау" - "Болжанған қолданбаны бекіту" + "Болжамды бекіту" "таңбаша орнату" "Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді." "негізгі экран параметрлері мен таңбашаларын оқу" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index e31985256d..b733699691 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -27,6 +27,8 @@ "បាន​បិទ​ធាតុ​ក្រាហ្វិក​ក្នុង​របៀប​សុវត្ថិភាព" "ផ្លូវកាត់មិនអាចប្រើបានទេ" "អេក្រង់ដើម" + + "មុខងារ​បំបែកអេក្រង់" "ព័ត៌មានកម្មវិធី​សម្រាប់ %1$s" "ការកំណត់ការប្រើប្រាស់សម្រាប់ %1$s" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 758d47c518..16b39f8bc2 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -27,6 +27,8 @@ "ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" "ಶಾರ್ಟ್‌ಕಟ್ ಲಭ್ಯವಿಲ್ಲ" "ಹೋಮ್" + + "ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್" "%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ" "%1$s ಗೆ ಸಂಬಂಧಿಸಿದ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" @@ -85,7 +87,7 @@ "ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್" "ಆ್ಯಪ್ ಮಾಹಿತಿ" "ಖಾಸಗಿಯಾಗಿ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" - "ಆ್ಯಪ್‌ ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" + "ಆ್ಯಪ್‌ ಅನ್ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ" "ಸ್ಥಾಪಿಸಿ" "ಆ್ಯಪ್ ಅನ್ನು ಸೂಚಿಸಬೇಡಿ" "ಮುನ್ನೋಟ ಪಿನ್ ಮಾಡಿ" @@ -192,6 +194,6 @@ "ಖಾಸಗಿ, ಲಾಕ್ ಮಾಡಲಾಗಿದೆ." "ಲಾಕ್ ಮಾಡಿ" "ಖಾಸಗಿ ಸ್ಪೇಸ್ ಪರಿವರ್ತನೆಯಾಗುತ್ತಿದೆ" - "ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" + "ಇನ್‌ಸ್ಟಾಲ್" "ಆ್ಯಪ್‌ಗಳನ್ನು ಪ್ರೈವೇಟ್ ಸ್ಪೇಸ್‌ನಲ್ಲಿ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 4d623fa30b..1d5c58f9d8 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -27,6 +27,8 @@ "안전 모드에서 위젯 사용 중지됨" "바로가기를 사용할 수 없음" "홈" + + "화면 분할" "%1$s 앱 정보" "%1$s의 사용량 설정" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 98d1e73439..6f01db33f7 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -27,6 +27,8 @@ "Виджеттер Коопсуз режимде өчүрүлгөн" "Кыска жол жок" "Башкы экран" + + "Экранды бөлүү" "%1$s колдонмосу жөнүндө маалымат" "%1$s колдонмосун пайдалануу параметрлери" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index e0bcfe0185..7ec103bc98 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -27,6 +27,8 @@ "​ວິດ​ເຈັດ​ຖືກ​ປິດ​ໃນ Safe mode" "ບໍ່ສາມາດໃຊ້ທາງລັດໄດ້" "ໂຮມສະກຣີນ" + + "ແບ່ງໜ້າຈໍ" "ຂໍ້ມູນແອັບສຳລັບ %1$s" "ການຕັ້ງຄ່າການນຳໃຊ້ສຳລັບ %1$s" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index 6a2b8d7f0f..1112474cd5 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -27,6 +27,8 @@ "Valdikliai išjungti Saugiame režime" "Sparčiojo klavišo negalima naudoti" "Pagrindinis" + + "Išskaidyto ekrano režimas" "Programos „%1$s“ informacija" "„%1$s“ naudojimo nustatymai" diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index cae6b6e211..4f1a92cb06 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -27,6 +27,8 @@ "Logrīki atspējoti drošajā režīmā" "Saīsne nav pieejama." "Sākums" + + "Sadalīt ekrānu" "%1$s: informācija par lietotni" "Lietojuma iestatījumi: %1$s" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 46d8600c3d..d984ca03d2 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -27,6 +27,8 @@ "Додатоците се оневозможени во безбеден режим" "Кратенката не е достапна" "Почетен екран" + + "Поделен екран" "Податоци за апликација за %1$s" "Поставки за користење за %1$s" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index eec5f74a54..ea8849eb5c 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -27,6 +27,8 @@ "സുരക്ഷിത മോഡിൽ വിജറ്റുകൾ പ്രവർത്തനരഹിതമാക്കി" "കുറുക്കുവഴി ലഭ്യമല്ല" "ഹോം" + + "സ്‌ക്രീൻ വിഭജന മോഡ്" "%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ" "%1$s എന്നതിനുള്ള ഉപയോഗ ക്രമീകരണം" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 396589c796..8554717ca1 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -27,6 +27,8 @@ "Safe горимд виджетүүдийг идэвхгүйжүүлсэн" "Товчлол алга" "Нүүр" + + "Дэлгэцийг хуваах" "%1$s-н аппын мэдээлэл" "%1$s-н ашиглалтын тохиргоо" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 972c9f2342..dcdf25c290 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -27,6 +27,8 @@ "विजेट सुरक्षित मोडमध्ये अक्षम झाले" "शॉर्टकट उपलब्ध नाही" "होम" + + "स्प्लिट स्क्रीन" "%1$s साठी ॲपशी संबंधित माहिती" "%1$s साठी वापरासंबंधित सेटिंग्ज" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index c25e3df9d6..22ee2cb1e7 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -27,6 +27,8 @@ "Widget dilumpuhkan dalam mod Selamat" "Pintasan tidak tersedia" "Rumah" + + "Skrin pisah" "Maklumat apl untuk %1$s" "Tetapan penggunaan sebanyak %1$s" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 700278a454..bca1c6eed9 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -27,6 +27,8 @@ "လုံခြုံရေး မုဒ်ထဲမှာ ဝီဂျက်များကို ပိတ်ထား" "ဖြတ်လမ်း မရနိုင်ပါ" "ပင်မစာမျက်နှာ" + + "မျက်နှာပြင် ခွဲ၍ပြသခြင်း" "%1$s အတွက် အက်ပ်အချက်အလက်" "%1$s အတွက် အသုံးပြုမှုဆက်တင်များ" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index c2f99aa052..1440443422 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -27,6 +27,8 @@ "Moduler er deaktivert i sikker modus" "Snarveien er ikke tilgjengelig" "Startskjerm" + + "Delt skjerm" "Appinformasjon for %1$s" "Bruksinnstillinger for %1$s" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 5e93f89654..52613cb857 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -27,6 +27,8 @@ "सुरक्षित मोडमा विगेटहरू अक्षम गरियो" "सर्टकट उपलब्ध छैन" "होम" + + "स्प्लिट स्क्रिन" "%1$s का हकमा एपसम्बन्धी जानकारी" "%1$s को प्रयोगसम्बन्धी सेटिङ" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index c2e5ebda96..90dcd466d1 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -27,6 +27,8 @@ "Widgets uitgezet in veilige modus" "Snelkoppeling is niet beschikbaar" "Startscherm" + + "Gesplitst scherm" "App-info voor %1$s" "Gebruiksinstellingen voor %1$s" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index 3c240ae129..6d2f87ef20 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -27,6 +27,8 @@ "ନିରାପଦ ମୋଡରେ ୱିଜେଟ୍‌ ଅକ୍ଷମ କରାଗଲା" "ଶର୍ଟକଟ୍‌ ଉପଲବ୍ଧ ନାହିଁ" "ହୋମ" + + "ସ୍କ୍ରିନ‌କୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ" "%1$s ପାଇଁ ଆପ ସୂଚନା" "%1$s ପାଇଁ ବ୍ୟବହାର ସେଟିଂସ" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 0df0c3f274..c235c3cdc5 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -27,6 +27,8 @@ "ਵਿਜੇਟ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ" "ਸ਼ਾਰਟਕੱਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" "ਮੁੱਖ ਪੰਨਾ" + + "ਸਪਲਿਟ ਸਕ੍ਰੀਨ" "%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ" "%1$s ਲਈ ਵਰਤੋਂ ਸੈਟਿੰਗਾਂ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index a8e79e3a50..685b7d911d 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -27,6 +27,8 @@ "Widżety są wyłączone w trybie bezpiecznym" "Skrót nie jest dostępny" "Ekran główny" + + "Podziel ekran" "Informacje o aplikacji: %1$s" "%1$s – ustawienia użycia" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 6e4a8e89cb..14a3cf52f4 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -27,6 +27,8 @@ "Widgets desativados no Modo de segurança" "O atalho não está disponível" "Página inicial" + + "Ecrã dividido" "Informações da app para %1$s" "Definições de utilização para %1$s" @@ -190,7 +192,7 @@ "Definições do espaço privado" "Privado, desbloqueado." "Privado, bloqueado." - "Bloquear" + "Bloqueio" "Transição do espaço privado" "Instalar" "Instale apps no espaço privado" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index a7eb0a71a6..b2ec45d3fc 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -27,6 +27,8 @@ "Widgets desativados no modo de segurança" "O atalho não está disponível" "Início" + + "Tela dividida" "Informações do app %1$s" "Configurações de uso de %1$s" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index bbade3c666..256fa60964 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -27,6 +27,8 @@ "Widgeturile sunt dezactivate în modul de siguranță" "Comanda rapidă nu este disponibilă" "Pagina de pornire" + + "Ecran împărțit" "Informații despre aplicație pentru %1$s" "Setări de utilizare pentru %1$s" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 995052e8f7..402143dde7 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -27,6 +27,8 @@ "Виджеты отключены в безопасном режиме" "Ярлык недоступен" "Главный экран" + + "Разделить экран" "Сведения о приложении \"%1$s\"" "Настройки использования приложения \"%1$s\"" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 914085416c..455f18b777 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -27,6 +27,8 @@ "සුරක්ෂිත ආකාරය තුළ විජටය අබල කරන ලදි" "කෙටි මග ලබා ගත නොහැකිය" "මුල් පිටුව" + + "බෙදුම් තිරය" "%1$s සඳහා යෙදුම් තතු" "%1$s සඳහා භාවිත සැකසීම්" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 1ba5771180..7771cf7b46 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -27,6 +27,8 @@ "Miniaplikácie sú v núdzovom režime zakázané" "Skratky nie sú k dispozícii" "Domov" + + "Rozdeliť obrazovku" "Informácie o aplikácii pre %1$s" "Nastavenia používania pre %1$s" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index cea6e1832c..2e75b1761c 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -27,6 +27,8 @@ "Pripomočki so onemogočeni v varnem načinu" "Bližnjica ni na voljo" "Začetni zaslon" + + "Razdeljen zaslon" "Podatki o aplikaciji za: %1$s" "Nastavitve uporabe za »%1$s«" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index f328557dc9..a00f11a6b3 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -27,6 +27,8 @@ "Miniaplikacionet janë të çaktivizuara në modalitetin e sigurt" "Shkurtorja nuk është e disponueshme" "Ekrani bazë" + + "Ekrani i ndarë" "Informacioni i aplikacionit për %1$s" "Cilësimet e përdorimit për \"%1$s\"" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 6fdeb418c6..97d3ff48e7 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -27,6 +27,8 @@ "Виџети су онемогућени у Безбедном режиму" "Пречица није доступна" "Почетни екран" + + "Подељени екран" "Информације о апликацији за: %1$s" "Подешавања потрошње за %1$s" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 1866f95b02..8a8524e6ef 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -27,6 +27,8 @@ "Widgets är inaktiverade i felsäkert läge" "Genvägen är inte tillgänglig" "Startskärm" + + "Delad skärm" "Appinformation för %1$s" "Användningsinställningar för %1$s" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 5c02beb2f5..64f629608e 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -27,6 +27,8 @@ "Wijeti zimezimwa katika hali ya Usalama" "Hakuna njia ya mkato" "Skrini ya kwanza" + + "Gawa skrini" "Maelezo ya programu ya %1$s" "Mipangilio ya matumizi ya %1$s" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index c45b3ddb87..189f4ced83 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -27,6 +27,8 @@ "பாதுகாப்புப் பயன்முறையில் விட்ஜெட்கள் முடக்கப்பட்டுள்ளன" "ஷார்ட்கட் இல்லை" "முகப்பு" + + "திரைப் பிரிப்பு" "%1$sக்கான ஆப்ஸ் தகவல்கள்" "%1$sக்கான உபயோக அமைப்புகள்" @@ -88,7 +90,7 @@ "ஆப்ஸை நிறுவல் நீக்கு" "நிறுவு" "பரிந்துரைக்காதே" - "கணிக்கப்பட்ட ஆப்ஸைப் பின் செய்தல்" + "கணிக்கப்பட்டதைப் பின் செய்" "குறுக்குவழிகளை நிறுவுதல்" "பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் ஆப்ஸை அனுமதிக்கிறது." "முகப்புத் திரையின் அமைப்புகளையும் ஷார்ட்கட்களையும் படித்தல்" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index e1c4668b0f..d789baa843 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -27,6 +27,8 @@ "సురక్షిత మోడ్‌లో విడ్జెట్‌లు నిలిపివేయబడ్డాయి" "షార్ట్‌కట్ అందుబాటులో లేదు" "మొదటి ట్యాబ్" + + "స్ప్లిట్ స్క్రీన్" "%1$s కోసం యాప్ సమాచారం" "%1$sకు సంబంధించిన వినియోగ సెట్టింగ్‌లు" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 4288c24936..f89638d8f2 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -27,6 +27,8 @@ "มีการปิดใช้งานวิดเจ็ตในเซฟโหมด" "ทางลัดไม่พร้อมใช้งาน" "หน้าแรก" + + "แยกหน้าจอ" "ข้อมูลแอปสำหรับ %1$s" "การตั้งค่าการใช้งานสำหรับ %1$s" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 305f5322c4..8754a12a49 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -27,6 +27,8 @@ "Naka-disable ang mga widget sa Safe mode" "Hindi available ang shortcut" "Home" + + "Split screen" "Impormasyon ng app para sa %1$s" "Mga setting ng paggamit para sa %1$s" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index e8c7593912..761ce56704 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -27,6 +27,8 @@ "Güvenli modda widget\'lar devre dışı" "Kısayol kullanılamıyor" "Ana ekran" + + "Bölünmüş ekran" "%1$s uygulama bilgileri" "%1$s ile ilgili kullanım ayarları" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index c1d6b2fa85..2c85d5a292 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -27,6 +27,8 @@ "У безпечному режимі віджети вимкнено" "Ярлик недоступний" "Головний екран" + + "Розділити екран" "Інформація про додаток для %1$s" "Параметри використання (%1$s)" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 6c1a88e95c..09f4304744 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -27,6 +27,8 @@ "ویجیٹس کو محفوظ وضع میں غیر فعال کر دیا گیا" "شارٹ کٹ دستیاب نہیں ہے" "ہوم" + + "اسپلٹ اسکرین" "‏%1$s کے لیے ایپ کی معلومات" "‏%1$s کیلئے استعمال کی ترتیبات" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 18431cc068..d8dea69c4b 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -27,6 +27,8 @@ "Xavfsiz rejimda vidjetlar o‘chirib qo‘yilgan" "Tezkor tugmadan foydalanib bo‘lmaydi" "Bosh ekran" + + "Ekranni ikkiga ajratish" "%1$s ilovasi axboroti" "%1$s uchun sarf sozlamalari" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index b5fb1d7463..172c995629 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -27,6 +27,8 @@ "Tiện ích bị vô hiệu hóa ở chế độ an toàn" "Lối tắt không khả dụng" "Màn hình chính" + + "Chia đôi màn hình" "Thông tin ứng dụng cho %1$s" "Chế độ cài đặt mức sử dụng %1$s" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index d51f8fd9c3..9c658dc88a 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -27,6 +27,8 @@ "安全模式下不允许使用微件" "无法使用快捷方式" "主屏幕" + + "分屏" "%1$s 的应用信息" "%1$s的使用设置" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 90ff5151ab..af32638c17 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -27,6 +27,8 @@ "在安全模式中無法使用小工具" "沒有可用的捷徑" "主畫面" + + "分割螢幕" "%1$s 的應用程式資料" "「%1$s」的用量設定" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 023a5265c1..54a1c5dd50 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -27,6 +27,8 @@ "在安全模式下無法使用小工具" "目前無法使用捷徑" "主畫面" + + "分割畫面" "「%1$s」的應用程式資訊" "「%1$s」的用量設定" @@ -87,7 +89,7 @@ "安裝在私人空間中" "解除安裝應用程式" "安裝" - "不要提供應用程式建議" + "不要建議此應用程式" "固定預測的應用程式" "安裝捷徑" "允許應用程式自動新增捷徑。" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index a9367250c2..9752e184b0 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -27,6 +27,8 @@ "Amawijethi akhutshaziwe kwimodi yokuphepha" "Isinqamuleli asitholakali" "Ikhaya" + + "Hlukanisa isikrini" "Ulwazi lwe-App ye-%1$s" "Amasethingi okusetshenziswa ka-%1$s" From d87d9e262b679436736a58807ccb5b30a7663787 Mon Sep 17 00:00:00 2001 From: Uwais Ashraf Date: Thu, 13 Jun 2024 12:19:57 +0000 Subject: [PATCH 129/143] Refresh overlay on new snapshot taken even if an old snapshot exists Bug: 302041971 Test: Manual checking of overlay refreshes in bug repro case - live tile and select Test: Manual checking of no additional overlay refreshes on non-live tile select Test: Manually ensured no additional overlay refreshes while scrolling Test: presubmit Flag: EXEMPT bugfix Change-Id: I5d455560d0bf816f86042078a662f06f5d1397bb --- .../quickstep/views/TaskThumbnailViewDeprecated.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java index 447002f2a6..4283d0e4cf 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java @@ -61,6 +61,8 @@ import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.recents.utilities.PreviewPositionHelper; +import java.util.Objects; + /** * A task in the Recents view. * @@ -222,14 +224,16 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab public void setThumbnail(@Nullable Task task, @Nullable ThumbnailData thumbnailData, boolean refreshNow) { mTask = task; - boolean thumbnailWasNull = mThumbnailData == null; + ThumbnailData oldThumbnailData = mThumbnailData; mThumbnailData = (thumbnailData != null && thumbnailData.getThumbnail() != null) ? thumbnailData : null; if (mTask != null) { updateSplashView(mTask.icon); } if (refreshNow) { - refresh(thumbnailWasNull && mThumbnailData != null); + Long oldSnapshotId = oldThumbnailData != null ? oldThumbnailData.getSnapshotId() : null; + Long snapshotId = mThumbnailData != null ? mThumbnailData.getSnapshotId() : null; + refresh(snapshotId != null && !Objects.equals(oldSnapshotId, snapshotId)); } } From 7cc4302f1096a260b48cbc8fecfe0526d0b2eb8e Mon Sep 17 00:00:00 2001 From: Charlie Anderson Date: Wed, 29 May 2024 11:21:46 -0400 Subject: [PATCH 130/143] Send additional Extras in first screen broadcasts, to help with app archiving. - refactor FirstScreenBroadcast.java into FirstScreenBroadcastHelper.kt - send Extras to include installed/archived items on first screen - send Extras to include installed/archived widgets on all screens. - truncate items to limit Broadcast size Bug: 322314760 Test: unit testing and E2E test of B&R Flag: launcher_broadcast_installed_apps Change-Id: I214149ac0c63f177d3d1ca0b6d0cb11be37f4ae0 --- .../launcher3/model/FirstScreenBroadcast.java | 2 +- .../model/FirstScreenBroadcastHelper.kt | 387 ++++++++++++++++++ .../model/FirstScreenBroadcastModel.kt | 39 ++ .../android/launcher3/model/LoaderTask.java | 26 +- .../launcher3/provider/RestoreDbTask.java | 4 +- .../launcher3/util/PackageManagerHelper.java | 15 +- .../model/FirstScreenBroadcastHelperTest.kt | 386 +++++++++++++++++ 7 files changed, 849 insertions(+), 10 deletions(-) create mode 100644 src/com/android/launcher3/model/FirstScreenBroadcastHelper.kt create mode 100644 src/com/android/launcher3/model/FirstScreenBroadcastModel.kt create mode 100644 tests/src/com/android/launcher3/model/FirstScreenBroadcastHelperTest.kt diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java index cc20cd194c..f443f8142e 100644 --- a/src/com/android/launcher3/model/FirstScreenBroadcast.java +++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java @@ -96,7 +96,7 @@ public class FirstScreenBroadcast { .collect(groupingBy(SessionInfo::getInstallerPackageName, mapping(SessionInfo::getAppPackageName, Collectors.toSet()))) .forEach((installer, packages) -> - sendBroadcastToInstaller(context, installer, packages, firstScreenItems)); + sendBroadcastToInstaller(context, installer, packages, firstScreenItems)); } /** diff --git a/src/com/android/launcher3/model/FirstScreenBroadcastHelper.kt b/src/com/android/launcher3/model/FirstScreenBroadcastHelper.kt new file mode 100644 index 0000000000..aa62c32e33 --- /dev/null +++ b/src/com/android/launcher3/model/FirstScreenBroadcastHelper.kt @@ -0,0 +1,387 @@ +/* + * 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.model + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInstaller.SessionInfo +import android.os.Process +import android.util.Log +import androidx.annotation.AnyThread +import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread +import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP +import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT +import com.android.launcher3.model.data.CollectionInfo +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.pm.InstallSessionHelper +import com.android.launcher3.util.Executors +import com.android.launcher3.util.PackageManagerHelper +import com.android.launcher3.util.PackageUserKey + +/** + * Helper class to send broadcasts to package installers that have: + * - Pending Items on first screen + * - Installed/Archived Items on first screen + * - Installed/Archived Widgets on every screen + * + * The packages are broken down by: folder items, workspace items, hotseat items, and widgets. + * Package installers only receive data for items that they are installing or have installed. + */ +object FirstScreenBroadcastHelper { + @VisibleForTesting const val MAX_BROADCAST_SIZE = 70 + + private const val TAG = "FirstScreenBroadcastHelper" + private const val DEBUG = true + private const val ACTION_FIRST_SCREEN_ACTIVE_INSTALLS = + "com.android.launcher3.action.FIRST_SCREEN_ACTIVE_INSTALLS" + // String retained as "folderItem" for back-compatibility reasons. + private const val PENDING_COLLECTION_ITEM_EXTRA = "folderItem" + private const val PENDING_WORKSPACE_ITEM_EXTRA = "workspaceItem" + private const val PENDING_HOTSEAT_ITEM_EXTRA = "hotseatItem" + private const val PENDING_WIDGET_ITEM_EXTRA = "widgetItem" + // Extras containing all installed items, including Archived Apps. + private const val INSTALLED_WORKSPACE_ITEMS_EXTRA = "workspaceInstalledItems" + private const val INSTALLED_HOTSEAT_ITEMS_EXTRA = "hotseatInstalledItems" + // This includes installed widgets on all screens, not just first. + private const val ALL_INSTALLED_WIDGETS_ITEM_EXTRA = "widgetInstalledItems" + private const val VERIFICATION_TOKEN_EXTRA = "verificationToken" + + /** + * Return list of [FirstScreenBroadcastModel] for each installer and their + * installing/installed/archived items. If the FirstScreenBroadcastModel data is greater in size + * than [MAX_BROADCAST_SIZE], then we will truncate the data until it meets the size limit to + * avoid overloading the broadcast. + * + * @param packageManagerHelper helper for querying PackageManager + * @param firstScreenItems every ItemInfo on first screen + * @param userKeyToSessionMap map of pending SessionInfo's for installing items + * @param allWidgets list of all Widgets added to every screen + */ + @WorkerThread + @JvmStatic + fun createModelsForFirstScreenBroadcast( + packageManagerHelper: PackageManagerHelper, + firstScreenItems: List, + userKeyToSessionMap: Map, + allWidgets: List + ): List { + + // installers for installing items + val pendingItemInstallerMap: Map> = + createPendingItemsMap(userKeyToSessionMap) + val installingPackages = pendingItemInstallerMap.values.flatten().toSet() + + // installers for installed items on first screen + val installedItemInstallerMap: Map> = + createInstalledItemsMap(firstScreenItems, installingPackages, packageManagerHelper) + + // installers for widgets on all screens + val allInstalledWidgetsMap: Map> = + createAllInstalledWidgetsMap(allWidgets, installingPackages, packageManagerHelper) + + val allInstallers: Set = + pendingItemInstallerMap.keys + + installedItemInstallerMap.keys + + allInstalledWidgetsMap.keys + val models = mutableListOf() + // create broadcast for each installer, with extras for each item category + allInstallers.forEach { installer -> + val installingItems = pendingItemInstallerMap[installer] + val broadcastModel = + FirstScreenBroadcastModel(installerPackage = installer).apply { + addPendingItems(installingItems, firstScreenItems) + addInstalledItems(installer, installedItemInstallerMap) + addAllScreenWidgets(installer, allInstalledWidgetsMap) + } + broadcastModel.truncateModelForBroadcast() + models.add(broadcastModel) + } + return models + } + + /** From the model data, create Intents to send broadcasts and fire them. */ + @WorkerThread + @JvmStatic + fun sendBroadcastsForModels(context: Context, models: List) { + for (model in models) { + model.printDebugInfo() + val intent = + Intent(ACTION_FIRST_SCREEN_ACTIVE_INSTALLS) + .setPackage(model.installerPackage) + .putExtra( + VERIFICATION_TOKEN_EXTRA, + PendingIntent.getActivity( + context, + 0 /* requestCode */, + Intent(), + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE + ) + ) + .putStringArrayListExtra( + PENDING_COLLECTION_ITEM_EXTRA, + ArrayList(model.pendingCollectionItems) + ) + .putStringArrayListExtra( + PENDING_WORKSPACE_ITEM_EXTRA, + ArrayList(model.pendingWorkspaceItems) + ) + .putStringArrayListExtra( + PENDING_HOTSEAT_ITEM_EXTRA, + ArrayList(model.pendingHotseatItems) + ) + .putStringArrayListExtra( + PENDING_WIDGET_ITEM_EXTRA, + ArrayList(model.pendingWidgetItems) + ) + .putStringArrayListExtra( + INSTALLED_WORKSPACE_ITEMS_EXTRA, + ArrayList(model.installedWorkspaceItems) + ) + .putStringArrayListExtra( + INSTALLED_HOTSEAT_ITEMS_EXTRA, + ArrayList(model.installedHotseatItems) + ) + .putStringArrayListExtra( + ALL_INSTALLED_WIDGETS_ITEM_EXTRA, + ArrayList( + model.firstScreenInstalledWidgets + + model.secondaryScreenInstalledWidgets + ) + ) + context.sendBroadcast(intent) + } + } + + /** Maps Installer packages to Set of app packages from install sessions */ + private fun createPendingItemsMap( + userKeyToSessionMap: Map + ): Map> { + val myUser = Process.myUserHandle() + val result = mutableMapOf>() + userKeyToSessionMap.forEach { entry -> + if (!myUser.equals(InstallSessionHelper.getUserHandle(entry.value))) return@forEach + val installer = entry.value.installerPackageName + val appPackage = entry.value.appPackageName + if (installer.isNullOrEmpty() || appPackage.isNullOrEmpty()) return@forEach + result.getOrPut(installer) { mutableSetOf() }.add(appPackage) + } + return result + } + + /** + * Maps Installer packages to Set of ItemInfo from first screen. Filter out installing packages. + */ + private fun createInstalledItemsMap( + firstScreenItems: List, + installingPackages: Set, + packageManagerHelper: PackageManagerHelper + ): Map> { + val result = mutableMapOf>() + firstScreenItems.forEach { item -> + val appPackage = getPackageName(item) ?: return@forEach + if (installingPackages.contains(appPackage)) return@forEach + val installer = packageManagerHelper.getAppInstallerPackage(appPackage) + if (installer.isNullOrEmpty()) return@forEach + result.getOrPut(installer) { mutableSetOf() }.add(item) + } + return result + } + + /** + * Maps Installer packages to Set of AppWidget packages installed on all screens. Filter out + * installing packages. + */ + private fun createAllInstalledWidgetsMap( + allWidgets: List, + installingPackages: Set, + packageManagerHelper: PackageManagerHelper + ): Map> { + val result = mutableMapOf>() + allWidgets + .sortedBy { widget -> widget.screenId } + .forEach { widget -> + val appPackage = getPackageName(widget) ?: return@forEach + if (installingPackages.contains(appPackage)) return@forEach + val installer = packageManagerHelper.getAppInstallerPackage(appPackage) + if (installer.isNullOrEmpty()) return@forEach + result.getOrPut(installer) { mutableSetOf() }.add(widget) + } + return result + } + + /** + * Add first screen Pending Items from Map to [FirstScreenBroadcastModel] for given installer + */ + private fun FirstScreenBroadcastModel.addPendingItems( + installingItems: Set?, + firstScreenItems: List + ) { + if (installingItems == null) return + for (info in firstScreenItems) { + addCollectionItems(info, installingItems) + val packageName = getPackageName(info) ?: continue + if (!installingItems.contains(packageName)) continue + when { + info is LauncherAppWidgetInfo -> pendingWidgetItems.add(packageName) + info.container == CONTAINER_HOTSEAT -> pendingHotseatItems.add(packageName) + info.container == CONTAINER_DESKTOP -> pendingWorkspaceItems.add(packageName) + } + } + } + + /** + * Add first screen installed Items from Map to [FirstScreenBroadcastModel] for given installer + */ + private fun FirstScreenBroadcastModel.addInstalledItems( + installer: String, + installedItemInstallerMap: Map>, + ) { + installedItemInstallerMap[installer]?.forEach { info -> + val packageName: String = getPackageName(info) ?: return@forEach + when (info.container) { + CONTAINER_HOTSEAT -> installedHotseatItems.add(packageName) + CONTAINER_DESKTOP -> installedWorkspaceItems.add(packageName) + } + } + } + + /** Add Widgets on every screen from Map to [FirstScreenBroadcastModel] for given installer */ + private fun FirstScreenBroadcastModel.addAllScreenWidgets( + installer: String, + allInstalledWidgetsMap: Map> + ) { + allInstalledWidgetsMap[installer]?.forEach { widget -> + val packageName: String = getPackageName(widget) ?: return@forEach + if (widget.screenId == 0) { + firstScreenInstalledWidgets.add(packageName) + } else { + secondaryScreenInstalledWidgets.add(packageName) + } + } + } + + private fun FirstScreenBroadcastModel.addCollectionItems( + info: ItemInfo, + installingPackages: Set + ) { + if (info !is CollectionInfo) return + pendingCollectionItems.addAll( + cloneOnMainThread(info.getAppContents()) + .mapNotNull { getPackageName(it) } + .filter { installingPackages.contains(it) } + ) + } + + /** + * Creates a copy of [FirstScreenBroadcastModel] with items truncated to meet + * [MAX_BROADCAST_SIZE] in a prioritized order. + */ + @VisibleForTesting + fun FirstScreenBroadcastModel.truncateModelForBroadcast() { + val totalItemCount = getTotalItemCount() + if (totalItemCount <= MAX_BROADCAST_SIZE) return + var extraItemCount = totalItemCount - MAX_BROADCAST_SIZE + + while (extraItemCount > 0) { + // In this order, remove items until we meet the max size limit. + when { + pendingCollectionItems.isNotEmpty() -> + pendingCollectionItems.apply { remove(last()) } + pendingHotseatItems.isNotEmpty() -> pendingHotseatItems.apply { remove(last()) } + installedHotseatItems.isNotEmpty() -> installedHotseatItems.apply { remove(last()) } + secondaryScreenInstalledWidgets.isNotEmpty() -> + secondaryScreenInstalledWidgets.apply { remove(last()) } + pendingWidgetItems.isNotEmpty() -> pendingWidgetItems.apply { remove(last()) } + firstScreenInstalledWidgets.isNotEmpty() -> + firstScreenInstalledWidgets.apply { remove(last()) } + pendingWorkspaceItems.isNotEmpty() -> pendingWorkspaceItems.apply { remove(last()) } + installedWorkspaceItems.isNotEmpty() -> + installedWorkspaceItems.apply { remove(last()) } + } + extraItemCount-- + } + } + + /** Returns count of all Items held by [FirstScreenBroadcastModel]. */ + @VisibleForTesting + fun FirstScreenBroadcastModel.getTotalItemCount() = + pendingCollectionItems.size + + pendingWorkspaceItems.size + + pendingHotseatItems.size + + pendingWidgetItems.size + + installedWorkspaceItems.size + + installedHotseatItems.size + + firstScreenInstalledWidgets.size + + secondaryScreenInstalledWidgets.size + + private fun FirstScreenBroadcastModel.printDebugInfo() { + if (DEBUG) { + Log.d( + TAG, + "Sending First Screen Broadcast for installer=$installerPackage" + + ", total packages=${getTotalItemCount()}" + ) + pendingCollectionItems.forEach { + Log.d(TAG, "$installerPackage:Pending Collection item:$it") + } + pendingWorkspaceItems.forEach { + Log.d(TAG, "$installerPackage:Pending Workspace item:$it") + } + pendingHotseatItems.forEach { Log.d(TAG, "$installerPackage:Pending Hotseat item:$it") } + pendingWidgetItems.forEach { Log.d(TAG, "$installerPackage:Pending Widget item:$it") } + installedWorkspaceItems.forEach { + Log.d(TAG, "$installerPackage:Installed Workspace item:$it") + } + installedHotseatItems.forEach { + Log.d(TAG, "$installerPackage:Installed Hotseat item:$it") + } + firstScreenInstalledWidgets.forEach { + Log.d(TAG, "$installerPackage:Installed Widget item (first screen):$it") + } + secondaryScreenInstalledWidgets.forEach { + Log.d(TAG, "$installerPackage:Installed Widget item (secondary screens):$it") + } + } + } + + private fun getPackageName(info: ItemInfo): String? { + var packageName: String? = null + if (info is LauncherAppWidgetInfo) { + info.providerName?.let { packageName = info.providerName.packageName } + } else if (info.targetComponent != null) { + packageName = info.targetComponent?.packageName + } + return packageName + } + + /** + * Clone the provided list on UI thread. This is used for [FolderInfo.getContents] which is + * always modified on UI thread. + */ + @AnyThread + private fun cloneOnMainThread(list: ArrayList): List { + return try { + return Executors.MAIN_EXECUTOR.submit> { ArrayList(list) } + .get() + } catch (e: Exception) { + emptyList() + } + } +} diff --git a/src/com/android/launcher3/model/FirstScreenBroadcastModel.kt b/src/com/android/launcher3/model/FirstScreenBroadcastModel.kt new file mode 100644 index 0000000000..ba5c526144 --- /dev/null +++ b/src/com/android/launcher3/model/FirstScreenBroadcastModel.kt @@ -0,0 +1,39 @@ +/* + * 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.model + +/** Data model for the information used for [FirstScreenBroadcastHelper] Broadcast Extras */ +data class FirstScreenBroadcastModel( + // Package name of the installer for all items + val installerPackage: String, + // Installing items in Folders + val pendingCollectionItems: MutableSet = mutableSetOf(), + // Installing items on first screen + val pendingWorkspaceItems: MutableSet = mutableSetOf(), + // Installing items on hotseat + val pendingHotseatItems: MutableSet = mutableSetOf(), + // Installing widgets on first screen + val pendingWidgetItems: MutableSet = mutableSetOf(), + // Installed/Archived Items on first screen + val installedWorkspaceItems: MutableSet = mutableSetOf(), + // Installed/Archived items on hotseat + val installedHotseatItems: MutableSet = mutableSetOf(), + // Installed/Archived Widgets on first screen + val firstScreenInstalledWidgets: MutableSet = mutableSetOf(), + // Installed Archived Widgets on secondary screens + val secondaryScreenInstalledWidgets: MutableSet = mutableSetOf() +) diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 0d40a2432e..dc6968c7d9 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -47,6 +47,7 @@ import android.os.Bundle; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.util.ArrayMap; import android.util.Log; import android.util.LongSparseArray; @@ -195,17 +196,32 @@ public class LoaderTask implements Runnable { } private void sendFirstScreenActiveInstallsBroadcast() { - ArrayList firstScreenItems = new ArrayList<>(); - ArrayList allItems = mBgDataModel.getAllWorkspaceItems(); - // Screen set is never empty IntArray allScreens = mBgDataModel.collectWorkspaceScreens(); final int firstScreen = allScreens.get(0); IntSet firstScreens = IntSet.wrap(firstScreen); + ArrayList allItems = mBgDataModel.getAllWorkspaceItems(); + ArrayList firstScreenItems = new ArrayList<>(); filterCurrentWorkspaceItems(firstScreens, allItems, firstScreenItems, new ArrayList<>() /* otherScreenItems are ignored */); - mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems); + final int launcherBroadcastInstalledApps = Settings.Secure.getInt( + mApp.getContext().getContentResolver(), + "launcher_broadcast_installed_apps", + /* def= */ 0); + if (launcherBroadcastInstalledApps == 1) { + List broadcastModels = + FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast( + mPmHelper, + firstScreenItems, + mInstallingPkgsCached, + mBgDataModel.appWidgets + ); + logASplit("Sending first screen broadcast with additional archiving Extras"); + FirstScreenBroadcastHelper.sendBroadcastsForModels(mApp.getContext(), broadcastModels); + } else { + mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems); + } } public void run() { @@ -249,7 +265,7 @@ public class LoaderTask implements Runnable { mModelDelegate.workspaceLoadComplete(); // Notify the installer packages of packages with active installs on the first screen. sendFirstScreenActiveInstallsBroadcast(); - logASplit("sendFirstScreenActiveInstallsBroadcast"); + logASplit("sendFirstScreenBroadcast"); // Take a break waitForIdle(); diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index a4ff29f33a..21897bffb8 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -418,9 +418,7 @@ public class RestoreDbTask { DeviceGridState deviceGridState = new DeviceGridState(context); FileLog.d(TAG, "restore initiated from backup: DeviceGridState=" + deviceGridState); LauncherPrefs.get(context).putSync(RESTORE_DEVICE.to(deviceGridState.getDeviceType())); - if (enableLauncherBrMetricsFixed()) { - LauncherPrefs.get(context).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(true)); - } + LauncherPrefs.get(context).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(true)); } @WorkerThread diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index f7c4df4527..8c5a76e665 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -16,9 +16,10 @@ package com.android.launcher3.util; -import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE; import static android.view.WindowManager.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI; +import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE; + import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; @@ -150,6 +151,18 @@ public class PackageManagerHelper implements SafeCloseable{ } } + /** + * Returns the installing app package for the given package + */ + public String getAppInstallerPackage(@NonNull final String packageName) { + try { + return mPm.getInstallSourceInfo(packageName).getInstallingPackageName(); + } catch (NameNotFoundException e) { + Log.e(TAG, "Failed to get installer package for app package:" + packageName, e); + return null; + } + } + /** * Returns the application info for the provided package or null */ diff --git a/tests/src/com/android/launcher3/model/FirstScreenBroadcastHelperTest.kt b/tests/src/com/android/launcher3/model/FirstScreenBroadcastHelperTest.kt new file mode 100644 index 0000000000..aadf72e801 --- /dev/null +++ b/tests/src/com/android/launcher3/model/FirstScreenBroadcastHelperTest.kt @@ -0,0 +1,386 @@ +/* + * 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.model + +import android.app.PendingIntent +import android.content.ComponentName +import android.content.Intent +import android.content.pm.PackageInstaller.SessionInfo +import android.os.UserHandle +import androidx.test.platform.app.InstrumentationRegistry +import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP +import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT +import com.android.launcher3.model.FirstScreenBroadcastHelper.MAX_BROADCAST_SIZE +import com.android.launcher3.model.FirstScreenBroadcastHelper.getTotalItemCount +import com.android.launcher3.model.FirstScreenBroadcastHelper.truncateModelForBroadcast +import com.android.launcher3.model.data.FolderInfo +import com.android.launcher3.model.data.LauncherAppWidgetInfo +import com.android.launcher3.model.data.WorkspaceItemInfo +import com.android.launcher3.util.PackageManagerHelper +import com.android.launcher3.util.PackageUserKey +import junit.framework.Assert.assertEquals +import org.junit.Test +import org.mockito.ArgumentCaptor +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class FirstScreenBroadcastHelperTest { + private val context = spy(InstrumentationRegistry.getInstrumentation().targetContext) + private val mockPmHelper = mock() + private val expectedAppPackage = "appPackageExpected" + private val expectedComponentName = ComponentName(expectedAppPackage, "expectedClass") + private val expectedInstallerPackage = "installerPackage" + private val expectedIntent = + Intent().apply { + component = expectedComponentName + setPackage(expectedAppPackage) + } + private val unexpectedAppPackage = "appPackageUnexpected" + private val unexpectedComponentName = ComponentName(expectedAppPackage, "unexpectedClass") + private val firstScreenItems = + listOf( + WorkspaceItemInfo().apply { + container = CONTAINER_DESKTOP + intent = expectedIntent + }, + WorkspaceItemInfo().apply { + container = CONTAINER_HOTSEAT + intent = expectedIntent + }, + LauncherAppWidgetInfo().apply { providerName = expectedComponentName } + ) + + @Test + fun `Broadcast Models are created with Pending Items from first screen`() { + // Given + val sessionInfoExpected = + SessionInfo().apply { + installerPackageName = expectedInstallerPackage + appPackageName = expectedAppPackage + } + val sessionInfoUnexpected = + SessionInfo().apply { + installerPackageName = expectedInstallerPackage + appPackageName = unexpectedAppPackage + } + val sessionInfoMap: HashMap = + hashMapOf( + PackageUserKey(unexpectedAppPackage, UserHandle(0)) to sessionInfoExpected, + PackageUserKey(expectedAppPackage, UserHandle(0)) to sessionInfoUnexpected + ) + + // When + val actualResult = + FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast( + packageManagerHelper = mockPmHelper, + firstScreenItems = firstScreenItems, + userKeyToSessionMap = sessionInfoMap, + allWidgets = listOf() + ) + + // Then + val expectedResult = + listOf( + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + pendingWorkspaceItems = mutableSetOf(expectedAppPackage), + pendingHotseatItems = mutableSetOf(expectedAppPackage), + pendingWidgetItems = mutableSetOf(expectedAppPackage) + ) + ) + + assertEquals(expectedResult, actualResult) + } + + @Test + fun `Broadcast Models are created with Installed Items from first screen`() { + // Given + whenever(mockPmHelper.getAppInstallerPackage(expectedAppPackage)) + .thenReturn(expectedInstallerPackage) + + // When + val actualResult = + FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast( + packageManagerHelper = mockPmHelper, + firstScreenItems = firstScreenItems, + userKeyToSessionMap = hashMapOf(), + allWidgets = + listOf( + LauncherAppWidgetInfo().apply { + providerName = expectedComponentName + screenId = 0 + } + ) + ) + + // Then + val expectedResult = + listOf( + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + installedHotseatItems = mutableSetOf(expectedAppPackage), + installedWorkspaceItems = mutableSetOf(expectedAppPackage), + firstScreenInstalledWidgets = mutableSetOf(expectedAppPackage) + ) + ) + assertEquals(expectedResult, actualResult) + } + + @Test + fun `Broadcast Models are created with Installed Widgets from every screen`() { + // Given + val expectedAppPackage2 = "appPackageExpected2" + val expectedComponentName2 = ComponentName(expectedAppPackage2, "expectedClass2") + whenever(mockPmHelper.getAppInstallerPackage(expectedAppPackage)) + .thenReturn(expectedInstallerPackage) + whenever(mockPmHelper.getAppInstallerPackage(expectedAppPackage2)) + .thenReturn(expectedInstallerPackage) + + // When + val actualResult = + FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast( + packageManagerHelper = mockPmHelper, + firstScreenItems = listOf(), + userKeyToSessionMap = hashMapOf(), + allWidgets = + listOf( + LauncherAppWidgetInfo().apply { + providerName = expectedComponentName + screenId = 0 + }, + LauncherAppWidgetInfo().apply { + providerName = expectedComponentName2 + screenId = 1 + }, + LauncherAppWidgetInfo().apply { + providerName = unexpectedComponentName + screenId = 0 + } + ) + ) + + // Then + val expectedResult = + listOf( + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + installedHotseatItems = mutableSetOf(), + installedWorkspaceItems = mutableSetOf(), + firstScreenInstalledWidgets = mutableSetOf(expectedAppPackage), + secondaryScreenInstalledWidgets = mutableSetOf(expectedAppPackage2) + ) + ) + assertEquals(expectedResult, actualResult) + } + + @Test + fun `Broadcast Models are created with Pending Items in Collections from the first screen`() { + // Given + val sessionInfoExpected = + SessionInfo().apply { + installerPackageName = expectedInstallerPackage + appPackageName = expectedAppPackage + } + val sessionInfoUnexpected = + SessionInfo().apply { + installerPackageName = expectedInstallerPackage + appPackageName = unexpectedAppPackage + } + val sessionInfoMap: HashMap = + hashMapOf( + PackageUserKey(unexpectedAppPackage, UserHandle(0)) to sessionInfoExpected, + PackageUserKey(expectedAppPackage, UserHandle(0)) to sessionInfoUnexpected, + ) + val expectedItemInfo = WorkspaceItemInfo().apply { intent = expectedIntent } + val expectedFolderInfo = FolderInfo().apply { add(expectedItemInfo) } + val firstScreenItems = listOf(expectedFolderInfo) + + // When + val actualResult = + FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast( + packageManagerHelper = mockPmHelper, + firstScreenItems = firstScreenItems, + userKeyToSessionMap = sessionInfoMap, + allWidgets = listOf() + ) + + // Then + val expectedResult = + listOf( + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + pendingCollectionItems = mutableSetOf(expectedAppPackage) + ) + ) + assertEquals(expectedResult, actualResult) + } + + @Test + fun `Models with too many items get truncated to max Broadcast size`() { + // given + val broadcastModel = + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + pendingCollectionItems = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + pendingWorkspaceItems = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + pendingHotseatItems = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + pendingWidgetItems = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + installedWorkspaceItems = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + installedHotseatItems = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + firstScreenInstalledWidgets = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + secondaryScreenInstalledWidgets = + mutableSetOf().apply { repeat(20) { add(it.toString()) } } + ) + + // When + broadcastModel.truncateModelForBroadcast() + + // Then + assertEquals(MAX_BROADCAST_SIZE, broadcastModel.getTotalItemCount()) + } + + @Test + fun `Broadcast truncates installed Hotseat items before other installed items`() { + // Given + val broadcastModel = + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + installedWorkspaceItems = + mutableSetOf().apply { repeat(50) { add(it.toString()) } }, + firstScreenInstalledWidgets = + mutableSetOf().apply { repeat(10) { add(it.toString()) } }, + secondaryScreenInstalledWidgets = + mutableSetOf().apply { repeat(10) { add((it + 10).toString()) } }, + installedHotseatItems = + mutableSetOf().apply { repeat(10) { add(it.toString()) } }, + ) + + // When + broadcastModel.truncateModelForBroadcast() + + // Then + assertEquals(MAX_BROADCAST_SIZE, broadcastModel.getTotalItemCount()) + assertEquals(50, broadcastModel.installedWorkspaceItems.size) + assertEquals(10, broadcastModel.firstScreenInstalledWidgets.size) + assertEquals(10, broadcastModel.secondaryScreenInstalledWidgets.size) + assertEquals(0, broadcastModel.installedHotseatItems.size) + } + + @Test + fun `Broadcast truncates Widgets before the rest of the first screen items`() { + // Given + val broadcastModel = + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + installedWorkspaceItems = + mutableSetOf().apply { repeat(70) { add(it.toString()) } }, + firstScreenInstalledWidgets = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + secondaryScreenInstalledWidgets = + mutableSetOf().apply { repeat(20) { add(it.toString()) } }, + ) + + // When + broadcastModel.truncateModelForBroadcast() + + // Then + assertEquals(MAX_BROADCAST_SIZE, broadcastModel.getTotalItemCount()) + assertEquals(70, broadcastModel.installedWorkspaceItems.size) + assertEquals(0, broadcastModel.firstScreenInstalledWidgets.size) + assertEquals(0, broadcastModel.secondaryScreenInstalledWidgets.size) + } + + @Test + fun `Broadcasts are correctly formed with Extras for each Installer`() { + // Given + val broadcastModels: List = + listOf( + FirstScreenBroadcastModel( + installerPackage = expectedInstallerPackage, + pendingCollectionItems = mutableSetOf("pendingCollectionItem"), + pendingWorkspaceItems = mutableSetOf("pendingWorkspaceItem"), + pendingHotseatItems = mutableSetOf("pendingHotseatItems"), + pendingWidgetItems = mutableSetOf("pendingWidgetItems"), + installedWorkspaceItems = mutableSetOf("installedWorkspaceItems"), + installedHotseatItems = mutableSetOf("installedHotseatItems"), + firstScreenInstalledWidgets = mutableSetOf("firstScreenInstalledWidgetItems"), + secondaryScreenInstalledWidgets = mutableSetOf("secondaryInstalledWidgetItems") + ) + ) + val expectedPendingIntent = + PendingIntent.getActivity( + context, + 0 /* requestCode */, + Intent(), + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE + ) + + // When + FirstScreenBroadcastHelper.sendBroadcastsForModels(context, broadcastModels) + + // Then + val argumentCaptor = ArgumentCaptor.forClass(Intent::class.java) + verify(context).sendBroadcast(argumentCaptor.capture()) + + assertEquals( + "com.android.launcher3.action.FIRST_SCREEN_ACTIVE_INSTALLS", + argumentCaptor.value.action + ) + assertEquals(expectedInstallerPackage, argumentCaptor.value.`package`) + assertEquals( + expectedPendingIntent, + argumentCaptor.value.getParcelableExtra("verificationToken") + ) + assertEquals( + arrayListOf("pendingCollectionItem"), + argumentCaptor.value.getStringArrayListExtra("folderItem") + ) + assertEquals( + arrayListOf("pendingWorkspaceItem"), + argumentCaptor.value.getStringArrayListExtra("workspaceItem") + ) + assertEquals( + arrayListOf("pendingHotseatItems"), + argumentCaptor.value.getStringArrayListExtra("hotseatItem") + ) + assertEquals( + arrayListOf("pendingWidgetItems"), + argumentCaptor.value.getStringArrayListExtra("widgetItem") + ) + assertEquals( + arrayListOf("installedWorkspaceItems"), + argumentCaptor.value.getStringArrayListExtra("workspaceInstalledItems") + ) + assertEquals( + arrayListOf("installedHotseatItems"), + argumentCaptor.value.getStringArrayListExtra("hotseatInstalledItems") + ) + assertEquals( + arrayListOf("firstScreenInstalledWidgetItems", "secondaryInstalledWidgetItems"), + argumentCaptor.value.getStringArrayListExtra("widgetInstalledItems") + ) + } +} From 91fb2f2e5e2c1f61adb78fbcfebc22cdb9210b3a Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Thu, 13 Jun 2024 12:41:39 -0700 Subject: [PATCH 131/143] Fix flickering issues with divider during split animation This CL makes changes to the "split divider placeholder view", which was intended to cover up the backdrop a little during the split confirm animation. The placeholder view is now larger (fullscreen) and fades in with the animation movement, so there is no longer a period of time when it looks like an awkward rectangle. New timings and interpolators confirmed with UX. Also renamed some variables and added comments for clarity. Fixes: 344573331 Test: Manually verified that the visual bug no longer happens on large and small screen, and from desktop and Overview. Flag: EXEMPT bugfix Change-Id: I3b37f2b0478035d7a3181ae7c23962fe75a13b2c --- .../util/PhoneSplitToConfirmTimings.java | 2 + .../util/SplitAnimationController.kt | 61 +++++++------------ .../quickstep/util/SplitToConfirmTimings.java | 10 +++ .../util/SplitToWorkspaceController.java | 7 +-- .../util/TabletSplitToConfirmTimings.java | 2 + .../android/quickstep/views/RecentsView.java | 13 ++-- 6 files changed, 46 insertions(+), 49 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java index 3d9e09ee81..cbe0f19c01 100644 --- a/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java +++ b/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java @@ -27,6 +27,8 @@ public class PhoneSplitToConfirmTimings public int getPlaceholderIconFadeInEnd() { return 133; } public int getStagedRectSlideStart() { return 0; } public int getStagedRectSlideEnd() { return 333; } + public int getBackingScrimFadeInStart() { return 0; } + public int getBackingScrimFadeInEnd() { return 266; } public int getDuration() { return PHONE_CONFIRM_DURATION; } } diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt index 8243ededd2..4bef51851c 100644 --- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt +++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt @@ -281,64 +281,45 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } /** - * Creates and returns a view to fade in at .4 animation progress and adds it to the provided - * [pendingAnimation]. Assumes that animation will be the final split placeholder launch anim. - * - * [secondPlaceholderEndingBounds] refers to the second placeholder view that gets added on - * screen, not the logical second app. For landscape it's the left app and for portrait the top - * one. + * Creates and returns a fullscreen scrim to fade in behind the split confirm animation, and + * adds it to the provided [pendingAnimation]. */ - fun addDividerPlaceholderViewToAnim( + fun addScrimBehindAnim( pendingAnimation: PendingAnimation, container: RecentsViewContainer, - secondPlaceholderEndingBounds: Rect, context: Context ): View { - val mSplitDividerPlaceholderView = View(context) + val scrim = View(context) val recentsView = container.getOverviewPanel>() - val dp: com.android.launcher3.DeviceProfile = container.getDeviceProfile() + val dp: DeviceProfile = container.getDeviceProfile() // Add it before/under the most recently added first floating taskView val firstAddedSplitViewIndex: Int = container .getDragLayer() .indexOfChild(recentsView.splitSelectController.firstFloatingTaskView) - container.getDragLayer().addView(mSplitDividerPlaceholderView, firstAddedSplitViewIndex) - val lp = mSplitDividerPlaceholderView.layoutParams as InsettableFrameLayout.LayoutParams + container.getDragLayer().addView(scrim, firstAddedSplitViewIndex) + // Make the scrim fullscreen + val lp = scrim.layoutParams as InsettableFrameLayout.LayoutParams lp.topMargin = 0 + lp.height = dp.heightPx + lp.width = dp.widthPx - if (dp.isLeftRightSplit) { - lp.height = secondPlaceholderEndingBounds.height() - lp.width = - container - .asContext() - .resources - .getDimensionPixelSize(R.dimen.split_divider_handle_region_height) - mSplitDividerPlaceholderView.translationX = - secondPlaceholderEndingBounds.right - lp.width / 2f - mSplitDividerPlaceholderView.translationY = 0f - } else { - lp.height = - container - .asContext() - .resources - .getDimensionPixelSize(R.dimen.split_divider_handle_region_height) - lp.width = secondPlaceholderEndingBounds.width() - mSplitDividerPlaceholderView.translationY = - secondPlaceholderEndingBounds.top - lp.height / 2f - mSplitDividerPlaceholderView.translationX = 0f - } - - mSplitDividerPlaceholderView.alpha = 0f - mSplitDividerPlaceholderView.setBackgroundColor( + scrim.alpha = 0f + scrim.setBackgroundColor( container.asContext().resources.getColor(R.color.taskbar_background_dark) ) - val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet) + val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet) as SplitToConfirmTimings pendingAnimation.setViewAlpha( - mSplitDividerPlaceholderView, + scrim, 1f, - Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f) + Interpolators.clampToProgress( + timings.backingScrimFadeInterpolator, + timings.backingScrimFadeInStartOffset, + timings.backingScrimFadeInEndOffset + ) ) - return mSplitDividerPlaceholderView + + return scrim } /** Does not play any animation if user is not currently in split selection state. */ diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java index d1ec2b6f23..7557ad1b86 100644 --- a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java +++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java @@ -17,6 +17,7 @@ package com.android.quickstep.util; import static com.android.app.animation.Interpolators.EMPHASIZED; +import static com.android.app.animation.Interpolators.LINEAR; import android.view.animation.Interpolator; @@ -31,6 +32,8 @@ abstract class SplitToConfirmTimings implements SplitAnimationTimings { abstract public int getPlaceholderIconFadeInEnd(); abstract public int getStagedRectSlideStart(); abstract public int getStagedRectSlideEnd(); + abstract public int getBackingScrimFadeInStart(); + abstract public int getBackingScrimFadeInEnd(); // Common timings public int getInstructionsFadeStart() { return 0; } @@ -39,6 +42,7 @@ abstract class SplitToConfirmTimings implements SplitAnimationTimings { public Interpolator getStagedRectYInterpolator() { return EMPHASIZED; } public Interpolator getStagedRectScaleXInterpolator() { return EMPHASIZED; } public Interpolator getStagedRectScaleYInterpolator() { return EMPHASIZED; } + public Interpolator getBackingScrimFadeInterpolator() { return LINEAR; } abstract public int getDuration(); @@ -48,4 +52,10 @@ abstract class SplitToConfirmTimings implements SplitAnimationTimings { public float getInstructionsFadeEndOffset() { return (float) getInstructionsFadeEnd() / getDuration(); } + public float getBackingScrimFadeInStartOffset() { + return (float) getBackingScrimFadeInStart() / getDuration(); + } + public float getBackingScrimFadeInEndOffset() { + return (float) getBackingScrimFadeInEnd() / getDuration(); + } } diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java index 2396512866..4962367bd2 100644 --- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java @@ -163,9 +163,8 @@ public class SplitToWorkspaceController { new RectF(firstTaskStartingBounds), firstTaskEndingBounds, false /* fadeWithThumbnail */, true /* isStagedTask */); - View mSplitDividerPlaceholderView = recentsView.getSplitSelectController() - .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation, - mLauncher, secondTaskEndingBounds, view.getContext()); + View backingScrim = recentsView.getSplitSelectController().getSplitAnimationController() + .addScrimBehindAnim(pendingAnimation, mLauncher, view.getContext()); FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher, view, bitmap, icon, secondTaskStartingBounds); @@ -197,7 +196,7 @@ public class SplitToWorkspaceController { private void cleanUp() { mLauncher.getDragLayer().removeView(firstFloatingTaskView); mLauncher.getDragLayer().removeView(secondFloatingTaskView); - mLauncher.getDragLayer().removeView(mSplitDividerPlaceholderView); + mLauncher.getDragLayer().removeView(backingScrim); mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher); mController.resetState(); } diff --git a/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java index 3756b4af59..d74473ceaf 100644 --- a/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java +++ b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java @@ -27,6 +27,8 @@ public class TabletSplitToConfirmTimings public int getPlaceholderIconFadeInEnd() { return 250; } public int getStagedRectSlideStart() { return 0; } public int getStagedRectSlideEnd() { return 500; } + public int getBackingScrimFadeInStart() { return 0; } + public int getBackingScrimFadeInEnd() { return 400; } public int getDuration() { return TABLET_CONFIRM_DURATION; } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 9096b75eaa..01cc53490f 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -738,7 +738,11 @@ public abstract class RecentsView Date: Wed, 12 Jun 2024 18:29:54 -0700 Subject: [PATCH 132/143] Use BySelector to search for text in search results. Verify the text after it's collected. I ran the test 20 times and couldn't find the stale object exception being thrown. Bug: 340341450 Bug: 339737008 Test: Manual Flag: com.google.android.apps.nexuslauncher.enable_inject_private_space_tile Change-Id: Ib153205db36cdd8b5fba4734b8b68930857659ff --- .../launcher3/tapl/SearchResultFromQsb.java | 65 +++++++++---------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java index 4be46ab621..c58d16e7a0 100644 --- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java +++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java @@ -17,10 +17,12 @@ package com.android.launcher3.tapl; import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL; -import android.text.TextUtils; +import android.graphics.Rect; import android.widget.TextView; import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.Direction; import androidx.test.uiautomator.UiObject2; import java.util.ArrayList; @@ -34,10 +36,12 @@ public class SearchResultFromQsb implements SearchInputSource { // This particular ID change should happen with caution private static final String SEARCH_CONTAINER_RES_ID = "search_results_list_view"; protected final LauncherInstrumentation mLauncher; + private final UiObject2 mSearchContainer; SearchResultFromQsb(LauncherInstrumentation launcher) { mLauncher = launcher; mLauncher.waitForLauncherObject("search_container_all_apps"); + mSearchContainer = mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID); } /** Find the app from search results with app name. */ @@ -52,18 +56,9 @@ public class SearchResultFromQsb implements SearchInputSource { /** Find the web suggestion from search suggestion's title text */ public SearchWebSuggestion findWebSuggestion(String text) { - ArrayList webSuggestions = - new ArrayList<>(mLauncher.waitForObjectsInContainer( - mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID), - By.clazz(TextView.class))); - for (UiObject2 uiObject: webSuggestions) { - String currentString = uiObject.getText(); - if (currentString.equals(text)) { - return createWebSuggestion(uiObject); - } - } - mLauncher.fail("Web suggestion title: " + text + " not found"); - return null; + UiObject2 webSuggestion = mLauncher.waitForObjectInContainer(mSearchContainer, + getSearchResultSelector(text)); + return createWebSuggestion(webSuggestion); } protected SearchWebSuggestion createWebSuggestion(UiObject2 webSuggestion) { @@ -73,12 +68,24 @@ public class SearchResultFromQsb implements SearchInputSource { /** Find the total amount of views being displayed and return the size */ public int getSearchResultItemSize() { ArrayList searchResultItems = - new ArrayList<>(mLauncher.waitForObjectsInContainer( - mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID), + new ArrayList<>(mLauncher.waitForObjectsInContainer(mSearchContainer, By.clazz(TextView.class))); return searchResultItems.size(); } + /** + * Scroll down to make next page search results rendered. + */ + public void getNextPageSearchResults() { + final int searchContainerHeight = mLauncher.getVisibleBounds(mSearchContainer).height(); + // Start scrolling from center of the screen to top of the screen. + mLauncher.scroll(mSearchContainer, + Direction.DOWN, + new Rect(0, 0, 0, searchContainerHeight / 2), + /* steps= */ 10, + /*slowDown= */ false); + } + /** * Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only. * @param tapRight Tap on the right of bottom sheet if true, or left otherwise. @@ -121,25 +128,13 @@ public class SearchResultFromQsb implements SearchInputSource { /** Verify a tile is present by checking its title and subtitle. */ public void verifyTileIsPresent(String title, String subtitle) { - ArrayList searchResults = - new ArrayList<>(mLauncher.waitForObjectsInContainer( - mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID), - By.clazz(TextView.class))); - boolean foundTitle = false; - boolean foundSubtitle = false; - for (UiObject2 uiObject: searchResults) { - String currentString = uiObject.getText(); - if (TextUtils.equals(currentString, title)) { - foundTitle = true; - } else if (TextUtils.equals(currentString, subtitle)) { - foundSubtitle = true; - } - } - if (!foundTitle) { - mLauncher.fail("Tile not found for title: " + title); - } - if (!foundSubtitle) { - mLauncher.fail("Tile not found for subtitle: " + subtitle); - } + mLauncher.waitForObjectInContainer(mSearchContainer, + getSearchResultSelector(title)); + mLauncher.waitForObjectInContainer(mSearchContainer, + getSearchResultSelector(subtitle)); + } + + private BySelector getSearchResultSelector(String text) { + return By.clazz(TextView.class).text(text); } } From 563c2101cfc660c2d47f49bec87105b32a7ce6b6 Mon Sep 17 00:00:00 2001 From: mpodolian Date: Mon, 13 May 2024 15:26:58 +0100 Subject: [PATCH 133/143] Animate bubble bar icon sizes and padding Added animation for the updates of bubble bar icon sizes and padding Fixes: 335575529 Flag: com.android.wm.shell.enable_bubble_bar DEVELOPMENT Test: BubbleBarViewAnimatorTest Change-Id: I07d66b3a9d565f4fa6040c3c4bf4866e4d81a3a6 --- quickstep/res/layout/transient_taskbar.xml | 2 - .../taskbar/bubbles/BubbleBarBackground.kt | 13 +- .../taskbar/bubbles/BubbleBarView.java | 235 +++++++++++++----- .../bubbles/BubbleBarViewController.java | 59 +++-- 4 files changed, 204 insertions(+), 105 deletions(-) diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml index 7c55bf821c..f3c3383ff7 100644 --- a/quickstep/res/layout/transient_taskbar.xml +++ b/quickstep/res/layout/transient_taskbar.xml @@ -45,8 +45,6 @@ android:layout_gravity="bottom|end" android:layout_marginHorizontal="@dimen/transient_taskbar_bottom_margin" android:paddingTop="@dimen/bubblebar_pointer_visible_size" - android:paddingEnd="@dimen/taskbar_icon_spacing" - android:paddingStart="@dimen/taskbar_icon_spacing" android:visibility="gone" android:gravity="center" android:clipChildren="false" diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt index bc13c89855..25939e1eb5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt @@ -123,22 +123,23 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) ) // Create background path val backgroundPath = Path() + val topOffset = backgroundHeight - bounds.height().toFloat() val radius = backgroundHeight / 2f val left = bounds.left + (if (anchorLeft) 0f else bounds.width().toFloat() - width) val right = bounds.left + (if (anchorLeft) width else bounds.width().toFloat()) - val top = bounds.top + arrowVisibleHeight + val top = bounds.top - topOffset + arrowVisibleHeight + val bottom = bounds.top + bounds.height().toFloat() backgroundPath.addRoundRect(left, top, right, bottom, radius, radius, Path.Direction.CW) - addArrowPathIfNeeded(backgroundPath) + addArrowPathIfNeeded(backgroundPath, topOffset) // Draw background. canvas.drawPath(backgroundPath, fillPaint) canvas.drawPath(backgroundPath, strokePaint) - canvas.restore() } - private fun addArrowPathIfNeeded(sourcePath: Path) { + private fun addArrowPathIfNeeded(sourcePath: Path, topOffset: Float) { if (!showingArrow || arrowHeightFraction <= 0) return val arrowPath = Path() RoundedArrowDrawable.addDownPointingRoundedTriangleToPath( @@ -153,7 +154,7 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) arrowPath.transform(pathTransform) // shift to arrow position val arrowStart = bounds.left + arrowPositionX - (arrowWidth / 2f) - val arrowTop = (1 - arrowHeightFraction) * arrowVisibleHeight + val arrowTop = (1 - arrowHeightFraction) * arrowVisibleHeight - topOffset arrowPath.offset(arrowStart, arrowTop) // union with rectangle sourcePath.op(arrowPath, Path.Op.UNION) @@ -180,7 +181,7 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float) fillPaint.colorFilter = colorFilter } - fun setHeight(newHeight: Float) { + fun setBackgroundHeight(newHeight: Float) { backgroundHeight = newHeight } diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index 2efecfb4a5..c7c63e8f86 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -24,6 +24,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.content.Context; @@ -44,6 +45,7 @@ import androidx.dynamicanimation.animation.SpringForce; import com.android.launcher3.R; import com.android.launcher3.anim.SpringAnimationBuilder; import com.android.launcher3.util.DisplayController; +import com.android.wm.shell.Flags; import com.android.wm.shell.common.bubbles.BubbleBarLocation; import java.util.List; @@ -85,6 +87,7 @@ public class BubbleBarView extends FrameLayout { private static final int MAX_VISIBLE_BUBBLES_COLLAPSED = 2; private static final int ARROW_POSITION_ANIMATION_DURATION_MS = 200; private static final int WIDTH_ANIMATION_DURATION_MS = 200; + private static final int SCALE_ANIMATION_DURATION_MS = 200; private static final long FADE_OUT_ANIM_ALPHA_DURATION_MS = 50L; private static final long FADE_OUT_ANIM_ALPHA_DELAY_MS = 50L; @@ -135,13 +138,12 @@ public class BubbleBarView extends FrameLayout { private float mBubbleBarPadding; // The size of a bubble in the bar private float mIconSize; + // The scale of bubble icons + private float mIconScale = 1f; // The elevation of the bubbles within the bar private final float mBubbleElevation; private final float mDragElevation; private final int mPointerSize; - - private final Rect mTempBackgroundBounds = new Rect(); - // Whether the bar is expanded (i.e. the bubble activity is being displayed). private boolean mIsBarExpanded = false; // The currently selected bubble view. @@ -162,7 +164,8 @@ public class BubbleBarView extends FrameLayout { /** An animator used for scaling in a new bubble to the bubble bar while expanded. */ @Nullable private ValueAnimator mNewBubbleScaleInAnimator = null; - + @Nullable + private ValueAnimator mScalePaddingAnimator; @Nullable private Animator mBubbleBarLocationAnimator = null; @@ -217,42 +220,74 @@ public class BubbleBarView extends FrameLayout { setBackgroundDrawable(mBubbleBarBackground); mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS); - mWidthAnimator.addUpdateListener(animation -> { - updateBubblesLayoutProperties(mBubbleBarLocation); - invalidate(); - }); - mWidthAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationCancel(Animator animation) { - } - @Override - public void onAnimationEnd(Animator animation) { - mBubbleBarBackground.showArrow(mIsBarExpanded); - if (!mIsBarExpanded && mReorderRunnable != null) { - mReorderRunnable.run(); - mReorderRunnable = null; - } - // If the bar was just collapsed and the overflow was the last bubble that was - // selected, set the first bubble as selected. - if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null - && mSelectedBubbleView != null - && mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) { - BubbleView firstBubble = (BubbleView) getChildAt(0); - mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey()); - } - updateWidth(); - } + addAnimationCallBacks(mWidthAnimator, + /* onStart= */ () -> mBubbleBarBackground.showArrow(true), + /* onEnd= */ () -> { + mBubbleBarBackground.showArrow(mIsBarExpanded); + if (!mIsBarExpanded && mReorderRunnable != null) { + mReorderRunnable.run(); + mReorderRunnable = null; + } + // If the bar was just collapsed and the overflow was the last bubble that was + // selected, set the first bubble as selected. + if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null + && mSelectedBubbleView != null + && mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) { + BubbleView firstBubble = (BubbleView) getChildAt(0); + mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey()); + } + updateWidth(); + }, + /* onUpdate= */ animator -> { + updateBubblesLayoutProperties(mBubbleBarLocation); + invalidate(); + }); + } - @Override - public void onAnimationRepeat(Animator animation) { - } - @Override - public void onAnimationStart(Animator animation) { - mBubbleBarBackground.showArrow(true); - } - }); + /** + * Animates icon sizes and spacing between icons and bubble bar borders. + * + * @param newIconSize new icon size + * @param newBubbleBarPadding spacing between icons and bubble bar borders. + */ + public void animateBubbleBarIconSize(float newIconSize, float newBubbleBarPadding) { + if (!isIconSizeOrPaddingUpdated(newIconSize, newBubbleBarPadding)) { + return; + } + if (!Flags.animateBubbleSizeChange()) { + setIconSizeAndPadding(newIconSize, newBubbleBarPadding); + } + if (mScalePaddingAnimator != null && mScalePaddingAnimator.isRunning()) { + mScalePaddingAnimator.cancel(); + } + ValueAnimator scalePaddingAnimator = ValueAnimator.ofFloat(0f, 1f); + scalePaddingAnimator.setDuration(SCALE_ANIMATION_DURATION_MS); + boolean isPaddingUpdated = isPaddingUpdated(newBubbleBarPadding); + boolean isIconSizeUpdated = isIconSizeUpdated(newIconSize); + float initialScale = mIconScale; + float initialPadding = mBubbleBarPadding; + float targetScale = newIconSize / getScaledIconSize(); + + addAnimationCallBacks(scalePaddingAnimator, + /* onStart= */ null, + /* onEnd= */ () -> setIconSizeAndPadding(newIconSize, newBubbleBarPadding), + /* onUpdate= */ animator -> { + float transitionProgress = (float) animator.getAnimatedValue(); + if (isIconSizeUpdated) { + mIconScale = + initialScale + (targetScale - initialScale) * transitionProgress; + } + if (isPaddingUpdated) { + mBubbleBarPadding = initialPadding + + (newBubbleBarPadding - initialPadding) * transitionProgress; + } + updateBubblesLayoutProperties(mBubbleBarLocation); + invalidate(); + }); + scalePaddingAnimator.start(); + mScalePaddingAnimator = scalePaddingAnimator; } @Override @@ -267,28 +302,37 @@ public class BubbleBarView extends FrameLayout { } /** - * Sets new icon size and spacing between icons and bubble bar borders. + * Sets new icon sizes and newBubbleBarPadding between icons and bubble bar borders. * - * @param newIconSize new icon size - * @param spacing spacing between icons and bubble bar borders. + * @param newIconSize new icon size + * @param newBubbleBarPadding newBubbleBarPadding between icons and bubble bar borders. */ - // TODO(b/335575529): animate bubble bar icons size change - public void setIconSizeAndPadding(float newIconSize, float spacing) { + public void setIconSizeAndPadding(float newIconSize, float newBubbleBarPadding) { // TODO(b/335457839): handle new bubble animation during the size change - mBubbleBarPadding = spacing; + if (!isIconSizeOrPaddingUpdated(newIconSize, newBubbleBarPadding)) { + return; + } + mIconScale = 1f; + mBubbleBarPadding = newBubbleBarPadding; mIconSize = newIconSize; int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); + childView.setScaleY(mIconScale); + childView.setScaleY(mIconScale); FrameLayout.LayoutParams params = (LayoutParams) childView.getLayoutParams(); params.height = (int) mIconSize; params.width = (int) mIconSize; childView.setLayoutParams(params); } - mBubbleBarBackground.setHeight(getBubbleBarExpandedHeight()); + mBubbleBarBackground.setBackgroundHeight(getBubbleBarHeight()); updateLayoutParams(); } + private float getScaledIconSize() { + return mIconSize * mIconScale; + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -698,6 +742,11 @@ public class BubbleBarView extends FrameLayout { setLayoutParams(lp); } + private float getBubbleBarHeight() { + return mIsBarExpanded ? getBubbleBarExpandedHeight() + : getBubbleBarCollapsedHeight(); + } + /** @return the horizontal margin between the bubble bar and the edge of the screen. */ int getHorizontalMargin() { LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); @@ -714,7 +763,10 @@ public class BubbleBarView extends FrameLayout { final float expandedWidth = expandedWidth(); final float collapsedWidth = collapsedWidth(); int bubbleCount = getChildCount(); - final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f; + float viewBottom = mBubbleBarBounds.height() + (isExpanded() ? mPointerSize : 0); + float bubbleBarAnimatedTop = viewBottom - getBubbleBarHeight(); + // When translating X & Y the scale is ignored, so need to deduct it from the translations + final float ty = bubbleBarAnimatedTop + mBubbleBarPadding - getScaleIconShift(); final boolean animate = getVisibility() == VISIBLE; final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl()); // elevation state is opposite to widthState - when expanded all icons are flat @@ -729,8 +781,9 @@ public class BubbleBarView extends FrameLayout { bv.setDragTranslationX(0f); bv.setOffsetX(0f); + bv.setScaleX(mIconScale); + bv.setScaleY(mIconScale); bv.setTranslationY(ty); - // the position of the bubble when the bar is fully expanded final float expandedX = getExpandedBubbleTranslationX(i, bubbleCount, onLeft); // the position of the bubble when the bar is fully collapsed @@ -795,21 +848,28 @@ public class BubbleBarView extends FrameLayout { mBubbleBarBackground.setArrowPosition(arrowPosition); mBubbleBarBackground.setArrowHeightFraction(widthState); mBubbleBarBackground.setWidth(interpolatedWidth); + mBubbleBarBackground.setBackgroundHeight(getBubbleBarExpandedHeight()); + } + + private float getScaleIconShift() { + return (mIconSize - getScaledIconSize()) / 2; } private float getExpandedBubbleTranslationX(int bubbleIndex, int bubbleCount, boolean onLeft) { if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) { return 0; } - final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing; + final float iconAndSpacing = getScaledIconSize() + mExpandedBarIconsSpacing; + float translationX; if (mNewBubbleScaleInAnimator != null && mNewBubbleScaleInAnimator.isRunning()) { - return getExpandedBubbleTranslationXDuringScaleAnimation( + translationX = getExpandedBubbleTranslationXDuringScaleAnimation( bubbleIndex, bubbleCount, onLeft); } else if (onLeft) { - return (bubbleCount - bubbleIndex - 1) * iconAndSpacing; + translationX = mBubbleBarPadding + (bubbleCount - bubbleIndex - 1) * iconAndSpacing; } else { - return bubbleIndex * iconAndSpacing; + translationX = mBubbleBarPadding + bubbleIndex * iconAndSpacing; } + return translationX - getScaleIconShift(); } /** @@ -830,17 +890,17 @@ public class BubbleBarView extends FrameLayout { // compiler doesn't know that. return 0; } - final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing; + final float iconAndSpacing = getScaledIconSize() + mExpandedBarIconsSpacing; final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction(); // the new bubble is scaling in from the center, so we need to adjust its translation so // that the distance to the adjacent bubble scales at the same rate. - final float pivotAdjustment = -(1 - newBubbleScale) * mIconSize / 2f; + final float pivotAdjustment = -(1 - newBubbleScale) * getScaledIconSize() / 2f; if (onLeft) { if (bubbleIndex == 0) { // this is the animating bubble. use scaled spacing between it and the bubble to // its left - return (bubbleCount - 1) * mIconSize + return (bubbleCount - 1) * getScaledIconSize() + (bubbleCount - 2) * mExpandedBarIconsSpacing + newBubbleScale * mExpandedBarIconsSpacing + pivotAdjustment; @@ -862,13 +922,16 @@ public class BubbleBarView extends FrameLayout { if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) { return 0; } + float translationX; if (onLeft) { // Shift the first bubble only if there are more bubbles in addition to overflow - return bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED - ? mIconOverlapAmount : 0; + translationX = mBubbleBarPadding + ( + bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED + ? mIconOverlapAmount : 0); } else { - return bubbleIndex == 0 ? 0 : mIconOverlapAmount; + translationX = mBubbleBarPadding + (bubbleIndex == 0 ? 0 : mIconOverlapAmount); } + return translationX - getScaleIconShift(); } /** @@ -976,7 +1039,7 @@ public class BubbleBarView extends FrameLayout { final int index = indexOfChild(mSelectedBubbleView); final float selectedBubbleTranslationX = getExpandedBubbleTranslationX( index, getChildCount(), bubbleBarLocation.isOnLeft(isLayoutRtl())); - return getPaddingStart() + selectedBubbleTranslationX + mIconSize / 2f; + return selectedBubbleTranslationX + mIconSize / 2f; } private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) { @@ -990,7 +1053,7 @@ public class BubbleBarView extends FrameLayout { bubblePosition = index >= MAX_VISIBLE_BUBBLES_COLLAPSED ? MAX_VISIBLE_BUBBLES_COLLAPSED - 1 : index; } - return getPaddingStart() + bubblePosition * (mIconOverlapAmount) + mIconSize / 2f; + return mBubbleBarPadding + bubblePosition * (mIconOverlapAmount) + getScaledIconSize() / 2f; } @Override @@ -1038,7 +1101,6 @@ public class BubbleBarView extends FrameLayout { */ public float expandedWidth() { final int childCount = getChildCount(); - final int horizontalPadding = getPaddingStart() + getPaddingEnd(); // spaces amount is less than child count by 1, or 0 if no child views final float totalSpace; final float totalIconSize; @@ -1047,22 +1109,22 @@ public class BubbleBarView extends FrameLayout { // expanded, so we have at least 2 bubbles in the bubble bar. final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction(); totalSpace = (childCount - 2 + newBubbleScale) * mExpandedBarIconsSpacing; - totalIconSize = (childCount - 1 + newBubbleScale) * mIconSize; + totalIconSize = (childCount - 1 + newBubbleScale) * getScaledIconSize(); } else { totalSpace = Math.max(childCount - 1, 0) * mExpandedBarIconsSpacing; - totalIconSize = childCount * mIconSize; + totalIconSize = childCount * getScaledIconSize(); } - return totalIconSize + totalSpace + horizontalPadding; + return totalIconSize + totalSpace + 2 * mBubbleBarPadding; } private float collapsedWidth() { final int childCount = getChildCount(); - final int horizontalPadding = getPaddingStart() + getPaddingEnd(); + final float horizontalPadding = 2 * mBubbleBarPadding; // If there are more than 2 bubbles, the first 2 should be visible when collapsed. // Otherwise just the first bubble should be visible because we don't show the overflow. return childCount > MAX_VISIBLE_BUBBLES_COLLAPSED - ? mIconSize + mIconOverlapAmount + horizontalPadding - : mIconSize + horizontalPadding; + ? getScaledIconSize() + mIconOverlapAmount + horizontalPadding + : getScaledIconSize() + horizontalPadding; } private float getBubbleBarExpandedHeight() { @@ -1071,7 +1133,7 @@ public class BubbleBarView extends FrameLayout { float getBubbleBarCollapsedHeight() { // the pointer is invisible when collapsed - return mIconSize + mBubbleBarPadding * 2; + return getScaledIconSize() + mBubbleBarPadding * 2; } /** @@ -1103,6 +1165,7 @@ public class BubbleBarView extends FrameLayout { return mIsAnimatingNewBubble; } + private boolean hasOverview() { // Overview is always the last bubble View lastChild = getChildAt(getChildCount() - 1); @@ -1144,6 +1207,46 @@ public class BubbleBarView extends FrameLayout { setContentDescription(contentDesc); } + private boolean isIconSizeOrPaddingUpdated(float newIconSize, float newBubbleBarPadding) { + return isIconSizeUpdated(newIconSize) || isPaddingUpdated(newBubbleBarPadding); + } + + private boolean isIconSizeUpdated(float newIconSize) { + return Float.compare(mIconSize, newIconSize) != 0; + } + + private boolean isPaddingUpdated(float newBubbleBarPadding) { + return Float.compare(mBubbleBarPadding, newBubbleBarPadding) != 0; + } + + private void addAnimationCallBacks(@NonNull ValueAnimator animator, + @Nullable Runnable onStart, + @Nullable Runnable onEnd, + @Nullable ValueAnimator.AnimatorUpdateListener onUpdate) { + if (onUpdate != null) animator.addUpdateListener(onUpdate); + animator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationCancel(Animator animator) { + + } + + @Override + public void onAnimationStart(Animator animator) { + if (onStart != null) onStart.run(); + } + + @Override + public void onAnimationEnd(Animator animator) { + if (onEnd != null) onEnd.run(); + } + + @Override + public void onAnimationRepeat(Animator animator) { + + } + }); + } + /** Interface for BubbleBarView to communicate with its controller. */ interface Controller { diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java index 0bfd1d7669..eec095df56 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java @@ -108,9 +108,11 @@ public class BubbleBarViewController { mBubbleDragController = bubbleControllers.bubbleDragController; mTaskbarStashController = controllers.taskbarStashController; mTaskbarInsetsController = controllers.taskbarInsetsController; + mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController); - mActivity.addOnDeviceProfileChangeListener(dp -> setBubbleBarIconSize(dp.taskbarIconSize)); - setBubbleBarIconSize(mActivity.getDeviceProfile().taskbarIconSize); + mActivity.addOnDeviceProfileChangeListener( + dp -> updateBubbleBarIconSize(dp.taskbarIconSize, /* animate= */ true)); + updateBubbleBarIconSize(mActivity.getDeviceProfile().taskbarIconSize, /* animate= */ false); mBubbleBarScale.updateValue(1f); mBubbleClickListener = v -> onBubbleClicked(v); mBubbleBarClickListener = v -> onBubbleBarClicked(); @@ -123,8 +125,6 @@ public class BubbleBarViewController { mBoundsChangeListener.onBoundsChanged(); } }); - - mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController); mBarView.setController(new BubbleBarView.Controller() { @Override public float getBubbleBarTranslationY() { @@ -299,33 +299,6 @@ public class BubbleBarViewController { } } - private void setBubbleBarIconSize(int newIconSize) { - if (newIconSize == mIconSize) { - return; - } - Resources res = mActivity.getResources(); - DisplayMetrics dm = res.getDisplayMetrics(); - float smallIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - APP_ICON_SMALL_DP, dm); - float mediumIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - APP_ICON_MEDIUM_DP, dm); - float largeIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - APP_ICON_LARGE_DP, dm); - float smallMediumThreshold = (smallIconSize + mediumIconSize) / 2f; - float mediumLargeThreshold = (mediumIconSize + largeIconSize) / 2f; - mIconSize = newIconSize <= smallMediumThreshold - ? res.getDimensionPixelSize(R.dimen.bubblebar_icon_size_small) : - res.getDimensionPixelSize(R.dimen.bubblebar_icon_size); - float bubbleBarPadding = newIconSize >= mediumLargeThreshold - ? res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing_large) : - res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing); - - mBarView.setIconSizeAndPadding(mIconSize, bubbleBarPadding); - mBarView.setPadding((int) bubbleBarPadding, mBarView.getPaddingTop(), - (int) bubbleBarPadding, - mBarView.getPaddingBottom()); - } - /** Sets a callback that updates the selected bubble after the bubble bar collapses. */ public void setUpdateSelectedBubbleAfterCollapse( Consumer updateSelectedBubbleAfterCollapse) { @@ -360,6 +333,30 @@ public class BubbleBarViewController { // Modifying view related properties. // + private void updateBubbleBarIconSize(int newIconSize, boolean animate) { + Resources res = mActivity.getResources(); + DisplayMetrics dm = res.getDisplayMetrics(); + float smallIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + APP_ICON_SMALL_DP, dm); + float mediumIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + APP_ICON_MEDIUM_DP, dm); + float largeIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + APP_ICON_LARGE_DP, dm); + float smallMediumThreshold = (smallIconSize + mediumIconSize) / 2f; + float mediumLargeThreshold = (mediumIconSize + largeIconSize) / 2f; + mIconSize = newIconSize <= smallMediumThreshold + ? res.getDimensionPixelSize(R.dimen.bubblebar_icon_size_small) : + res.getDimensionPixelSize(R.dimen.bubblebar_icon_size); + float bubbleBarPadding = newIconSize >= mediumLargeThreshold + ? res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing_large) : + res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing); + if (animate) { + mBarView.animateBubbleBarIconSize(mIconSize, bubbleBarPadding); + } else { + mBarView.setIconSizeAndPadding(mIconSize, bubbleBarPadding); + } + } + /** * Sets the translation of the bubble bar during the swipe up gesture. */ From 267087150567a6ec4e6a029ef1613b760d803f53 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Mon, 3 Jun 2024 10:59:57 +0800 Subject: [PATCH 134/143] Send source rect hint to Shell via stopSwipePipToHome Launcher has calculated it, so shell side can use it directly to avoid inconsistency. Bug: 331315278 Test: Assume the target app support auto-pip and it doesn't draw under display cutout. E.g. LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES Enter PiP from 90 degrees to home with 0 degrees. The left side of pip should not flicker. Change-Id: Id09efc8a30eeef14a031d9db2ab1e00b6f3034bc --- quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java | 3 ++- quickstep/src/com/android/quickstep/SystemUiProxy.java | 4 ++-- .../com/android/quickstep/util/SwipePipToHomeAnimator.java | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 4752225ec6..cc14044c3f 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1582,7 +1582,8 @@ public abstract class AbsSwipeUpHandler, mSwipePipToHomeAnimator.getComponentName(), mSwipePipToHomeAnimator.getDestinationBounds(), mSwipePipToHomeAnimator.getContentOverlay(), - mSwipePipToHomeAnimator.getAppBounds()); + mSwipePipToHomeAnimator.getAppBounds(), + mSwipePipToHomeAnimator.getSourceRectHint()); windowAnim = mSwipePipToHomeAnimators; } else { diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 72f67fc544..766da7bbaf 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -653,11 +653,11 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle { * should be responsible for cleaning up the overlay. */ public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds, - SurfaceControl overlay, Rect appBounds) { + SurfaceControl overlay, Rect appBounds, Rect sourceRectHint) { if (mPip != null) { try { mPip.stopSwipePipToHome(taskId, componentName, destinationBounds, overlay, - appBounds); + appBounds, sourceRectHint); } catch (RemoteException e) { Log.w(TAG, "Failed call stopSwipePipToHome"); } diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java index f823affef9..c18bad0e9d 100644 --- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java +++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java @@ -272,6 +272,10 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { return mAppBounds; } + public Rect getSourceRectHint() { + return mSourceRectHint; + } + @Nullable public SurfaceControl getContentOverlay() { return mPipContentOverlay == null ? null : mPipContentOverlay.getLeash(); From fbd93ef9070788306ce090ac83a6433dbaaf6dc3 Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Fri, 14 Jun 2024 10:36:05 -0700 Subject: [PATCH 135/143] Aconfig flag for taskbar customization. Test: Presubmit Bug: 347281365 Flag: com.android.launcher3.enable_taskbar_customization Change-Id: I5a3959a8ca956329faa2df5d6bda297934e1ba62 --- aconfig/launcher.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig index fecc43d0b2..fe4be4af59 100644 --- a/aconfig/launcher.aconfig +++ b/aconfig/launcher.aconfig @@ -78,6 +78,13 @@ flag { bug: "296231746" } +flag { + name: "enable_taskbar_customization" + namespace: "launcher" + description: "Enables taskbar customization framework." + bug: "347281365" +} + flag { name: "enable_unfolded_two_pane_picker" namespace: "launcher" From 8780fd3bbc50ccd26c944a2119512b1dc4138794 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Fri, 14 Jun 2024 12:26:38 -0400 Subject: [PATCH 136/143] Update All Set screen background colors to match specs Flag: NONE fully released, color update Fixes: 345702208 Fixes: 322080618 Test: Launched All Set screen Change-Id: I432f5d686ffb714bdccb3881d948242661191a0d --- quickstep/res/values-night/colors.xml | 2 +- quickstep/res/values/colors.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstep/res/values-night/colors.xml b/quickstep/res/values-night/colors.xml index 8d03ce6f96..94100ba47a 100644 --- a/quickstep/res/values-night/colors.xml +++ b/quickstep/res/values-night/colors.xml @@ -22,7 +22,7 @@ #202124 #3c4043 - #FF000000 + @android:color/system_neutral1_900 ?androidprv:attr/colorAccentSecondaryVariant diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml index 14a916f68b..0f997f9b77 100644 --- a/quickstep/res/values/colors.xml +++ b/quickstep/res/values/colors.xml @@ -76,7 +76,7 @@ #80868b #bdc1c6 - #FFFFFFFF + @android:color/system_neutral1_50 #333333 From 9fb1f8043573d5bc3376f0786354fc8f7a9cf2cd Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 12 Jun 2024 13:46:35 -0400 Subject: [PATCH 137/143] Fix icon flash on app launch Flag: com.android.launcher3.enable_additional_home_animations Fixes: 343051344 Test: temp logs, launched apps from home, quickly swiped home while quick switching Change-Id: I91071d53f753eb7bc99305c46241de203bcfdc98 --- .../quickstep/SwipeUpAnimationLogic.java | 20 ++++++++++++------- .../android/quickstep/views/RecentsView.java | 4 ++++ .../android/launcher3/views/ClipIconView.java | 4 ++++ .../launcher3/views/FloatingIconView.java | 8 +++++++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java index fb54241592..ba33c62d9d 100644 --- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -17,6 +17,7 @@ package com.android.quickstep; import static com.android.app.animation.Interpolators.ACCELERATE_1_5; import static com.android.app.animation.Interpolators.LINEAR; +import static com.android.launcher3.Flags.enableAdditionalHomeAnimations; import static com.android.launcher3.PagedView.INVALID_PAGE; import android.animation.Animator; @@ -449,7 +450,7 @@ public abstract class SwipeUpAnimationLogic implements float alpha = mAnimationFactory.getWindowAlpha(progress); mHomeAnim.setPlayFraction(progress); - if (mTargetTaskView == null) { + if (!enableAdditionalHomeAnimations() || mTargetTaskView == null) { mHomeToWindowPositionMap.mapRect(mWindowCurrentRect, currentRect); mMatrix.setRectToRect(mCropRectF, mWindowCurrentRect, ScaleToFit.FILL); mLocalTransformParams @@ -464,10 +465,15 @@ public abstract class SwipeUpAnimationLogic implements mLocalTransformParams.applySurfaceParams( mLocalTransformParams.createSurfaceParams(this)); - mAnimationFactory.update( - currentRect, progress, mMatrix.mapRadius(cornerRadius), (int) (alpha * 255)); - if (mTargetTaskView == null) { + mAnimationFactory.update( + currentRect, + progress, + mMatrix.mapRadius(cornerRadius), + !enableAdditionalHomeAnimations() || mTargetTaskView == null + ? 0 : (int) (alpha * 255)); + + if (!enableAdditionalHomeAnimations() || mTargetTaskView == null) { return; } if (mAnimationFactory.isAnimatingIntoIcon() && mAnimationFactory.isAnimationReady()) { @@ -506,7 +512,7 @@ public abstract class SwipeUpAnimationLogic implements public void onAnimationStart(Animator animation) { setUp(); mHomeAnim.dispatchOnStart(); - if (mTargetTaskView == null) { + if (!enableAdditionalHomeAnimations() || mTargetTaskView == null) { return; } Rect thumbnailBounds = new Rect(); @@ -521,7 +527,7 @@ public abstract class SwipeUpAnimationLogic implements } private void setUp() { - if (mTargetTaskView == null) { + if (!enableAdditionalHomeAnimations() || mTargetTaskView == null) { return; } RecentsView recentsView = mTargetTaskView.getRecentsView(); @@ -542,7 +548,7 @@ public abstract class SwipeUpAnimationLogic implements } private void cleanUp() { - if (mTargetTaskView == null) { + if (!enableAdditionalHomeAnimations() || mTargetTaskView == null) { return; } RecentsView recentsView = mTargetTaskView.getRecentsView(); diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 3c0445f322..d6a5329dac 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -34,6 +34,7 @@ import static com.android.app.animation.Interpolators.clampToProgress; import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU; import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; +import static com.android.launcher3.Flags.enableAdditionalHomeAnimations; import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.Flags.enableRefactorTaskThumbnail; import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS; @@ -4485,6 +4486,9 @@ public abstract class RecentsView Date: Thu, 13 Jun 2024 09:38:58 -0700 Subject: [PATCH 138/143] Ignore the mismatched source rect hint When the app provided source rect hint does not match the aspect ratio, by a certain threshold, we ignore that and in turn apply content overlay during the enter animation, to avoid size change at the end. In button-navigation mode, some special logical's applied as to crop the content to its shorter edge for this case, which is inconsistent and we will address that later in a separate change set. Video: http://recall/-/aaaaaabFQoRHlzixHdtY/d4kLspMrqb7Xsc2JtkTW0m Flag: NONE bug fix Bug: 338616637 Test: Enter PiP from zoomed and non-zoomed video Change-Id: I5059553cb9b6c02810e9638bfaf29dde9ab6140f --- .../quickstep/util/SwipePipToHomeAnimator.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java index 2d606f384a..e44f14819a 100644 --- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java +++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java @@ -50,6 +50,8 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { private static final float END_PROGRESS = 1.0f; + private static final float PIP_ASPECT_RATIO_MISMATCH_THRESHOLD = 0.01f; + private final int mTaskId; private final ActivityInfo mActivityInfo; private final SurfaceControl mLeash; @@ -135,6 +137,7 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { mDestinationBoundsTransformed.set(destinationBoundsTransformed); mSurfaceTransactionHelper = new PipSurfaceTransactionHelper(cornerRadius, shadowRadius); + final float aspectRatio = destinationBounds.width() / (float) destinationBounds.height(); String reasonForCreateOverlay = null; // For debugging purpose. if (sourceRectHint.isEmpty()) { reasonForCreateOverlay = "Source rect hint is empty"; @@ -149,15 +152,20 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { } else if (!appBounds.contains(sourceRectHint)) { // This is a situation in which the source hint rect is outside the app bounds, so it is // not a valid rectangle to use for cropping app surface - sourceRectHint.setEmpty(); reasonForCreateOverlay = "Source rect hint exceeds display bounds " + sourceRectHint; + sourceRectHint.setEmpty(); + } else if (Math.abs( + aspectRatio - (sourceRectHint.width() / (float) sourceRectHint.height())) + > PIP_ASPECT_RATIO_MISMATCH_THRESHOLD) { + // The source rect hint does not aspect ratio + reasonForCreateOverlay = "Source rect hint does not match aspect ratio " + + sourceRectHint + " aspect ratio " + aspectRatio; + sourceRectHint.setEmpty(); } if (sourceRectHint.isEmpty()) { // Crop a Rect matches the aspect ratio and pivots at the center point. // To make the animation path simplified. - final float aspectRatio = destinationBounds.width() - / (float) destinationBounds.height(); if ((appBounds.width() / (float) appBounds.height()) > aspectRatio) { // use the full height. mSourceRectHint.set(0, 0, From b08ec848c4e24b883877bdd59463379fb38bc18b Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sun, 16 Jun 2024 23:09:01 -0700 Subject: [PATCH 139/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ifa72f8a78e474ba24eaea42a3163b87daae515bd --- quickstep/res/values-mr/strings.xml | 2 +- quickstep/res/values-pt-rPT/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index 7941156dbc..b053a216a7 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -95,7 +95,7 @@ "सिस्टीम नेव्हिगेशन सेटिंग्ज" "शेअर करा" "स्क्रीनशॉट" - "स्प्लिट" + "स्प्लिट करा" "ॲपची जोडी सेव्ह करा" "स्प्लिट स्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा" "स्प्लिट स्क्रीन वापरण्यासाठी दुसरे ॲप निवडा" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index dd00469e41..47498ccb82 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -57,7 +57,7 @@ "Deslize rapidamente com o dedo para retroceder" "Para voltar ao último ecrã, deslize rapidamente do limite esquerdo ou direito até ao centro do ecrã." "Para voltar ao último ecrã, deslize rapidamente com 2 dedos a partir da extremidade esquerda ou direita até ao centro do ecrã." - "Voltar" + "Retroceder" "Deslize rapidamente a partir da extremidade esquerda ou direita para o meio do ecrã" "Deslize rapidamente com o dedo a partir do limite inferior do ecrã" "Não faça uma pausa antes de soltar" From d06eb8a29d6912c10d12651d327323c4c77a226a Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sun, 16 Jun 2024 23:09:27 -0700 Subject: [PATCH 140/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I560b082a24e4bb9331d45bec4d3352bf225b313e --- quickstep/res/values-mr/strings.xml | 2 +- quickstep/res/values-pt-rPT/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index ab475e07d8..d299635234 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -94,7 +94,7 @@ "सिस्टीम नेव्हिगेशन सेटिंग्ज" "शेअर करा" "स्क्रीनशॉट" - "स्प्लिट" + "स्प्लिट करा" "ॲपची जोडी सेव्ह करा" "स्प्लिट स्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा" "स्प्लिट स्क्रीन वापरण्यासाठी दुसरे ॲप निवडा" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index 65e14d5003..ac7bdf334d 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -56,7 +56,7 @@ "Deslize rapidamente com o dedo para retroceder" "Para voltar ao último ecrã, deslize rapidamente do limite esquerdo ou direito até ao centro do ecrã." "Para voltar ao último ecrã, deslize rapidamente com 2 dedos a partir da extremidade esquerda ou direita até ao centro do ecrã." - "Voltar" + "Retroceder" "Deslize rapidamente a partir da extremidade esquerda ou direita para o meio do ecrã" "Deslize rapidamente com o dedo a partir do limite inferior do ecrã" "Não faça uma pausa antes de soltar" From 54da62f9f927514ba3b20c3d6fe8a15c273bf04b Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sun, 16 Jun 2024 23:10:24 -0700 Subject: [PATCH 141/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ia28133416a47a1221d5e709281aee37b0e415042 --- res/values-en-rCA/strings.xml | 3 +-- res/values-en-rXC/strings.xml | 3 +-- res/values-pa/strings.xml | 2 +- res/values-pt/strings.xml | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index e9f951b491..08ff6e7f82 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -27,8 +27,7 @@ "Widgets disabled in Safe mode" "Shortcut isn\'t available" "Home" - - + "Set %1$s as default home app in Settings" "Split screen" "App info for %1$s" "Usage settings for %1$s" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index fb08c7e581..fa6d1f1a87 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -27,8 +27,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎Widgets disabled in Safe mode‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎Shortcut isn\'t available‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎Home‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‎Set ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ as default home app in Settings‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎Split screen‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎App info for %1$s‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎Usage settings for %1$s‎‏‎‎‏‎" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index c235c3cdc5..b287b2fcd7 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -86,7 +86,7 @@ "ਹਟਾਓ" "ਅਣਸਥਾਪਤ ਕਰੋ" "ਐਪ ਜਾਣਕਾਰੀ" - "ਨਿੱਜੀ ਵਜੋਂ ਸਥਾਪਤ ਕਰੋ" + "ਪ੍ਰਾਈਵੇਟ ਵਜੋਂ ਸਥਾਪਤ ਕਰੋ" "ਐਪ ਅਣਸਥਾਪਤ ਕਰੋ" "ਸਥਾਪਤ ਕਰੋ" "ਐਪ ਦਾ ਸੁਝਾਅ ਨਾ ਦਿਓ" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index b2ec45d3fc..4c4b13bacd 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -192,7 +192,7 @@ "Configurações do Espaço particular" "Privada, desbloqueado." "Privada, bloqueado." - "Bloquear" + "Bloqueio" "Espaço particular em transição" "Instalar" "Instalar apps no espaço privado" From 4645316a61a1eace3e892c20441fc38189aabf73 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sun, 16 Jun 2024 23:10:52 -0700 Subject: [PATCH 142/143] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ib223b1dc82ae646244e2f471f2e930af61e71686 --- res/values-hi/strings.xml | 2 +- res/values-kk/strings.xml | 2 +- res/values-pa/strings.xml | 2 +- res/values-pt-rPT/strings.xml | 2 +- res/values-pt/strings.xml | 2 +- res/values-ta/strings.xml | 2 +- res/values-zh-rTW/strings.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index a22bcb9dee..8fb62e513c 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -87,7 +87,7 @@ "निजी तौर पर इंस्टॉल करें" "इंस्‍टॉल करें" "ऐप्लिकेशन का सुझाव न दें" - "सुझाए गए ऐप्लिकेशन को पिन करें" + "सुझाए गए ऐप पिन करें" "शॉर्टकट इंस्‍टॉल करें" "ऐप को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देती है." "होम स्क्रीन की सेटिंग और शॉर्टकट पढ़ने की अनुमति" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index ee987aefc9..3a7fe6ff52 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -87,7 +87,7 @@ "Құпия профильге орнату" "Орнату" "Қолданба ұсынбау" - "Болжанған қолданбаны бекіту" + "Болжамды бекіту" "таңбаша орнату" "Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді." "негізгі экран параметрлері мен таңбашаларын оқу" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index f1351c4332..40c05b324f 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -84,7 +84,7 @@ "ਹਟਾਓ" "ਅਣਸਥਾਪਤ ਕਰੋ" "ਐਪ ਜਾਣਕਾਰੀ" - "ਨਿੱਜੀ ਵਜੋਂ ਸਥਾਪਤ ਕਰੋ" + "ਪ੍ਰਾਈਵੇਟ ਵਜੋਂ ਸਥਾਪਤ ਕਰੋ" "ਸਥਾਪਤ ਕਰੋ" "ਐਪ ਦਾ ਸੁਝਾਅ ਨਾ ਦਿਓ" "ਪੂਰਵ-ਅਨੁਮਾਨ ਪਿੰਨ ਕਰੋ" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 7afb702c7f..2d7ae82a13 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -188,7 +188,7 @@ "Privado" "Definições do espaço privado" "Bloquear/desbloquear espaço privado" - "Bloquear" + "Bloqueio" "Transição do espaço privado" "Instalar apps" "Instale apps no espaço privado" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 67eb4a1914..25b59a66b5 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -188,7 +188,7 @@ "Particular" "Configurações do Espaço particular" "Bloquear/desbloquear o Espaço particular" - "Bloquear" + "Bloqueio" "Espaço particular em transição" "Instalar apps" "Instalar apps no espaço privado" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index 5dddae01de..d561ac5c02 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -87,7 +87,7 @@ "தனிப்பட்டதில் நிறுவு" "நிறுவு" "பரிந்துரைக்காதே" - "கணிக்கப்பட்ட ஆப்ஸைப் பின் செய்தல்" + "கணிக்கப்பட்டதைப் பின் செய்" "குறுக்குவழிகளை நிறுவுதல்" "பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் ஆப்ஸை அனுமதிக்கிறது." "முகப்புத் திரையின் அமைப்புகளையும் ஷார்ட்கட்களையும் படித்தல்" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 2986b32276..e3bd5722b1 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -86,7 +86,7 @@ "應用程式資訊" "安裝在私人空間中" "安裝" - "不要提供應用程式建議" + "不要建議此應用程式" "固定預測的應用程式" "安裝捷徑" "允許應用程式自動新增捷徑。" From 67b8de56ce3129cf1737448b0697a7db8c0722e5 Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Mon, 17 Jun 2024 10:25:35 -0700 Subject: [PATCH 143/143] Add orientation logic to taskbar icon specs Test: Presubmit Bug: 341146605 Flag: NONE Taskbar Customization Change-Id: Ia86d61fd6ac38d03e45b23ea2a424a5b0b33c12b --- .../customization/TaskbarFeatureEvaluator.kt | 4 +++- .../taskbar/customization/TaskbarIconSpecs.kt | 14 ++++++++------ .../taskbar/customization/TaskbarSpecsEvaluator.kt | 4 +++- .../customization/TaskbarSpecsEvaluatorTest.kt | 13 +++++++++++-- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt index 1ec075ffaa..668a87d6d9 100644 --- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt @@ -19,7 +19,6 @@ package com.android.launcher3.taskbar.customization import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning import com.android.launcher3.taskbar.TaskbarActivityContext import com.android.launcher3.taskbar.TaskbarControllers -import com.android.launcher3.taskbar.TaskbarRecentAppsController import com.android.launcher3.util.DisplayController /** Evaluates all the features taskbar can have. */ @@ -41,4 +40,7 @@ class TaskbarFeatureEvaluator( val isTransient: Boolean get() = DisplayController.isTransientTaskbar(taskbarActivityContext) + + val isLandscape: Boolean + get() = taskbarActivityContext.deviceProfile.isLandscape } diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt index 4cd895de4d..67bbcce7f6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt @@ -29,13 +29,15 @@ object TaskbarIconSpecs { val defaultPersistentIconSize = iconSize40dp val defaultTransientIconSize = iconSize44dp - // defined as row, columns val transientTaskbarIconSizeByGridSize = mapOf( - Pair(6, 5) to iconSize52dp, - Pair(4, 5) to iconSize48dp, - Pair(5, 4) to iconSize48dp, - Pair(4, 4) to iconSize48dp, - Pair(5, 6) to iconSize44dp, + TransientTaskbarIconSizeKey(6, 5, false) to iconSize52dp, + TransientTaskbarIconSizeKey(6, 5, true) to iconSize52dp, + TransientTaskbarIconSizeKey(4, 4, false) to iconSize48dp, + TransientTaskbarIconSizeKey(4, 4, true) to iconSize52dp, + TransientTaskbarIconSizeKey(4, 5, false) to iconSize48dp, + TransientTaskbarIconSizeKey(4, 5, true) to iconSize48dp, + TransientTaskbarIconSizeKey(5, 5, false) to iconSize44dp, + TransientTaskbarIconSizeKey(5, 5, true) to iconSize44dp, ) } diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt index 02e5947b32..0b7be40826 100644 --- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt @@ -22,7 +22,7 @@ class TaskbarSpecsEvaluator(private val taskbarFeatureEvaluator: TaskbarFeatureE fun getIconSizeByGrid(row: Int, column: Int): TaskbarIconSize { return if (taskbarFeatureEvaluator.isTransient) { TaskbarIconSpecs.transientTaskbarIconSizeByGridSize.getOrDefault( - Pair(row, column), + TransientTaskbarIconSizeKey(row, column, taskbarFeatureEvaluator.isLandscape), TaskbarIconSpecs.defaultTransientIconSize, ) } else { @@ -58,3 +58,5 @@ class TaskbarSpecsEvaluator(private val taskbarFeatureEvaluator: TaskbarFeatureE } data class TaskbarIconSize(val size: Int) + +data class TransientTaskbarIconSizeKey(val row: Int, val column: Int, val isLandscape: Boolean) diff --git a/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt b/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt index b637e7d4cf..0bf68ebe93 100644 --- a/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt +++ b/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt @@ -35,12 +35,21 @@ class TaskbarSpecsEvaluatorTest { private val taskbarSpecsEvaluator = spy(TaskbarSpecsEvaluator(taskbarFeatureEvaluator)) @Test - fun testGetIconSizeByGrid_whenTaskbarIsTransient_withValidRowAndColumn() { + fun testGetIconSizeByGrid_whenTaskbarIsTransient_withValidRowAndColumnInLandscape() { doReturn(true).whenever(taskbarFeatureEvaluator).isTransient - assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(6, 5)) + doReturn(true).whenever(taskbarFeatureEvaluator).isLandscape + assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(4, 4)) .isEqualTo(TaskbarIconSpecs.iconSize52dp) } + @Test + fun testGetIconSizeByGrid_whenTaskbarIsTransient_withValidRowAndColumnInPortrait() { + doReturn(true).whenever(taskbarFeatureEvaluator).isTransient + doReturn(false).whenever(taskbarFeatureEvaluator).isLandscape + assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(4, 4)) + .isEqualTo(TaskbarIconSpecs.iconSize48dp) + } + @Test fun testGetIconSizeByGrid_whenTaskbarIsTransient_withInvalidRowAndColumn() { doReturn(true).whenever(taskbarFeatureEvaluator).isTransient