diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index df0912478b..b1a62022e9 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -121,6 +121,17 @@
android:layout_weight="1"
android:visibility="gone" />
+
+
+
+
+
+ android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
\ No newline at end of file
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index d086da481d..7aaf7441a1 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -45,14 +45,24 @@
android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:visibility="gone" />
+
+
+
+
+ android:theme="@style/ThemeControlHighlightWorkspaceColor" />
+
\ No newline at end of file
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 9f648a7e69..cc3b30e9dc 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -28,10 +28,7 @@
launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
-
+
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index 36d7f86f25..89e9b3d9fd 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -42,10 +42,7 @@
views that do not inherint from TaskView only or create a generic TaskView that have
N number of tasks.
-->
-
-
+
-
+
diff --git a/quickstep/res/layout/task_thumbnail.xml b/quickstep/res/layout/task_thumbnail.xml
new file mode 100644
index 0000000000..f1a3d62021
--- /dev/null
+++ b/quickstep/res/layout/task_thumbnail.xml
@@ -0,0 +1,20 @@
+
+
\ No newline at end of file
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 5097ff99e7..af35fc352b 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -95,7 +95,7 @@
"Einstellungen der Systemsteuerung"
"Teilen"
"Screenshot"
- "Teilen"
+ "Splitscreen"
"App-Paar speichern"
"Für Splitscreen auf weitere App tippen"
"Für Splitscreen andere App auswählen"
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 159226eec3..0d43f1efd6 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -118,7 +118,7 @@
"Mostrar siempre la barra de tareas"
"Para mostrar siempre la barra de tareas en la parte inferior, mantén pulsada la línea divisoria"
"Mantén pulsada la tecla de acción para buscar lo que ves en pantalla"
- "El producto usa la parte seleccionada de tu pantalla para hacer búsquedas. Se aplican la <a href="%1$s">Política de Privacidad</a> y los <a href="%2$s">Términos del Servicio</a> de Google."
+ "Este producto usa la parte seleccionada de tu pantalla para hacer búsquedas. Se aplican la <a href="%1$s">Política de Privacidad</a> y los <a href="%2$s">Términos del Servicio</a> de Google."
"Cerrar"
"Hecho"
"Inicio"
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 766dabb19b..c445bc8b67 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -95,7 +95,7 @@
"Süsteemi navigeerimisseaded"
"Jaga"
"Ekraanipilt"
- "Eralda"
+ "Jaga pooleks"
"Salvesta rakendusepaar"
"Jagatud ekraanikuva kasutamiseks puudutage muud rakendust"
"Valige jagatud ekraanikuva jaoks muu rakendus."
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index b0694c1924..040976d45e 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -95,7 +95,7 @@
"Järjestelmän navigointiasetukset"
"Jaa"
"Kuvakaappaus"
- "Jaa"
+ "Jaettu näyttö"
"Tallenna pari"
"Avaa jaettu näyttö napauttamalla toista sovellusta"
"Käytä jaettua näyttöä valitsemalla toinen sovellus"
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index e696faf92c..ecde5a3af6 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -95,7 +95,7 @@
"စနစ် လမ်းညွှန် ဆက်တင်များ"
"မျှဝေရန်"
"ဖန်သားပြင်ဓာတ်ပုံ"
- "ခွဲထုတ်ရန်"
+ "ခွဲရန်"
"အက်ပ်အတွဲ သိမ်းရန်"
"မျက်နှာပြင် ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"
"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးရန် နောက်အက်ပ်တစ်ခုရွေးပါ"
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 1086f9f4ee..727f3e7519 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -95,7 +95,7 @@
"系统导航设置"
"分享"
"屏幕截图"
- "拆分"
+ "分屏"
"保存应用组合"
"点按另一个应用即可使用分屏"
"另外选择一个应用才可使用分屏模式"
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index b24be541a9..0b0df95c68 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -965,7 +965,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
mWindowLayoutParams.paramsForRotation[rot].height = size;
}
}
- mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+ mControllers.runAfterInit(
+ mControllers.taskbarInsetsController
+ ::onTaskbarOrBubblebarWindowHeightOrInsetsChanged);
notifyUpdateLayoutParams();
}
@@ -1451,7 +1453,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
});
}
- protected boolean isUserSetupComplete() {
+ public boolean isUserSetupComplete() {
return mIsUserSetupComplete;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index 8ad24934cc..e487f9fd40 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -24,8 +24,10 @@ import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Space
+import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.Utilities
+import com.android.launcher3.taskbar.TaskbarActivityContext
import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter
/**
@@ -73,6 +75,23 @@ abstract class AbstractNavButtonLayoutter(
return params
}
+ fun adjustForSetupInPhoneMode(
+ navButtonsLayoutParams: FrameLayout.LayoutParams,
+ navButtonsViewLayoutParams: FrameLayout.LayoutParams,
+ deviceProfile: DeviceProfile
+ ) {
+ val phoneOrPortraitSetupMargin =
+ resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
+ navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
+ navButtonsLayoutParams.bottomMargin =
+ if (!deviceProfile.isLandscape) 0
+ else
+ phoneOrPortraitSetupMargin -
+ resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
+ navButtonsViewLayoutParams.height =
+ resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
+ }
+
open fun repositionContextualContainer(
contextualContainer: ViewGroup,
buttonSize: Int,
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
index 1e9f09bd3f..2497fbb98e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
@@ -116,6 +116,7 @@ class NavButtonLayoutFactory {
isPhoneGestureMode -> {
PhoneGestureLayoutter(
resources,
+ navButtonsView,
navButtonContainer,
endContextualContainer,
startContextualContainer,
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
index 8d91f2c8b3..390ec342e1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
@@ -17,15 +17,19 @@
package com.android.launcher3.taskbar.navbutton
import android.content.res.Resources
+import android.view.Gravity
import android.view.ViewGroup
+import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Space
+import com.android.launcher3.DeviceProfile
import com.android.launcher3.taskbar.TaskbarActivityContext
/** Layoutter for showing gesture navigation on phone screen. No buttons here, no-op container */
class PhoneGestureLayoutter(
resources: Resources,
+ navButtonsView: NearestTouchFrame,
navBarContainer: LinearLayout,
endContextualContainer: ViewGroup,
startContextualContainer: ViewGroup,
@@ -42,8 +46,31 @@ class PhoneGestureLayoutter(
a11yButton,
space
) {
+ private val mNavButtonsView = navButtonsView
override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
+ // TODO: look into if we should use SetupNavLayoutter instead.
+ if (!context.isUserSetupComplete) {
+ // Since setup wizard only has back button enabled, it looks strange to be
+ // end-aligned, so start-align instead.
+ val navButtonsLayoutParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
+ val navButtonsViewLayoutParams =
+ mNavButtonsView.layoutParams as FrameLayout.LayoutParams
+ val deviceProfile: DeviceProfile = context.deviceProfile
+
+ navButtonsLayoutParams.marginEnd = 0
+ navButtonsLayoutParams.gravity = Gravity.START
+ context.setTaskbarWindowSize(context.setupWindowSize)
+
+ adjustForSetupInPhoneMode(
+ navButtonsLayoutParams,
+ navButtonsViewLayoutParams,
+ deviceProfile
+ )
+ mNavButtonsView.layoutParams = navButtonsViewLayoutParams
+ navButtonContainer.layoutParams = navButtonsLayoutParams
+ }
+
endContextualContainer.removeAllViews()
startContextualContainer.removeAllViews()
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
index 91042c385f..22a36301b3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
@@ -77,16 +77,11 @@ class SetupNavLayoutter(
navButtonsLayoutParams.height =
resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_height)
} else {
- val phoneOrPortraitSetupMargin =
- resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
- navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
- navButtonsLayoutParams.bottomMargin =
- if (!deviceProfile.isLandscape) 0
- else
- phoneOrPortraitSetupMargin -
- resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
- navButtonsViewLayoutParams.height =
- resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
+ adjustForSetupInPhoneMode(
+ navButtonsLayoutParams,
+ navButtonsViewLayoutParams,
+ deviceProfile
+ )
}
mNavButtonsView.layoutParams = navButtonsViewLayoutParams
navButtonContainer.layoutParams = navButtonsLayoutParams
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 6c1d4b192f..317e6f2145 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -21,7 +21,6 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
-import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
@@ -50,6 +49,7 @@ import com.android.quickstep.util.AnimUtils;
import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
+import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
/**
@@ -167,8 +167,8 @@ public final class RecentsViewStateController extends
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0;
- propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
- MULTI_PROPERTY_VALUE, overviewButtonAlpha, config.getInterpolator(
+ propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlphaSetter(),
+ OverviewActionsView.FLOAT_SETTER, overviewButtonAlpha, config.getInterpolator(
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 527a776d10..fc0df76c10 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -248,7 +248,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, fromState.showTaskThumbnailSplash() ? 1f : 0);
mRecentsView.setContentAlpha(1);
mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress());
- mLauncher.getActionsView().getVisibilityAlpha().setValue(
+ mLauncher.getActionsView().getVisibilityAlphaSetter().accept(
(fromState.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0 ? 1f : 0f);
mRecentsView.setTaskIconScaledDown(true);
diff --git a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
index f68f793e01..0f844e1ec6 100644
--- a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
+++ b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
@@ -154,7 +154,7 @@ class DeviceConfigWrapper private constructor(propReader: PropReader) {
}
companion object {
- val configHelper by lazy { DeviceConfigHelper(::DeviceConfigWrapper) }
+ @JvmStatic val configHelper by lazy { DeviceConfigHelper(::DeviceConfigWrapper) }
@JvmStatic fun get() = configHelper.config
}
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index cd9df264c1..f052a9d580 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -65,7 +65,6 @@ import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFutur
import com.android.systemui.shared.recents.view.RecentsTransition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@@ -336,7 +335,7 @@ public interface TaskShortcutFactory {
recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
boolean shouldShowActionsButtonInstead =
isLargeTileFocusedTask && isInExpectedScrollPosition;
- boolean hasUnpinnableApp = Arrays.stream(taskView.getTaskContainers())
+ boolean hasUnpinnableApp = taskView.getTaskContainers().stream()
.anyMatch(att -> att != null && att.getItemInfo() != null
&& ((att.getItemInfo().runtimeStatusFlags
& ItemInfoWithIcon.FLAG_NOT_PINNABLE) != 0));
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 2e76356b5d..1bf129c703 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -46,12 +46,10 @@ import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.util.MultiPropertyFactory;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.RecentsViewContainer;
/**
* State controller for fallback recents activity
@@ -98,8 +96,8 @@ public class FallbackRecentsStateController implements StateHandler(context)
+ .getOverviewPanel>()
+ .mRecentsViewData,
+ (parent as TaskView).mTaskViewData
+ )
+ }
private var uiState: TaskThumbnailUiState = Uninitialized
+ private var inheritedScale: Float = 1f
+
+ private var cornerRadius: Float = TaskCornerRadius.get(context)
+ private var fullscreenCornerRadius: Float = QuickStepContract.getWindowCornerRadius(context)
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
@@ -51,6 +73,27 @@ class TaskThumbnailView : View {
invalidate()
}
}
+ MainScope().launch { viewModel.recentsFullscreenProgress.collect { invalidateOutline() } }
+ MainScope().launch {
+ viewModel.inheritedScale.collect { viewModelInheritedScale ->
+ inheritedScale = viewModelInheritedScale
+ invalidateOutline()
+ }
+ }
+
+ clipToOutline = true
+ outlineProvider =
+ object : ViewOutlineProvider() {
+ override fun getOutline(view: View, outline: Outline) {
+ outline.setRoundRect(
+ 0,
+ 0,
+ view.measuredWidth,
+ view.measuredHeight,
+ getCurrentCornerRadius()
+ )
+ }
+ }
}
override fun onDraw(canvas: Canvas) {
@@ -60,19 +103,25 @@ class TaskThumbnailView : View {
}
}
- private fun drawTransparentUiState(canvas: Canvas) {
- canvas.drawRoundRect(
- 0f,
- 0f,
- measuredWidth.toFloat(),
- measuredHeight.toFloat(),
- // TODO(b/334826840) add rounded corners
- 0f,
- 0f,
- CLEAR_PAINT
- )
+ override fun onConfigurationChanged(newConfig: Configuration?) {
+ super.onConfigurationChanged(newConfig)
+
+ cornerRadius = TaskCornerRadius.get(context)
+ fullscreenCornerRadius = QuickStepContract.getWindowCornerRadius(context)
+ invalidateOutline()
}
+ private fun drawTransparentUiState(canvas: Canvas) {
+ canvas.drawRect(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat(), CLEAR_PAINT)
+ }
+
+ private fun getCurrentCornerRadius() =
+ Utilities.mapRange(
+ viewModel.recentsFullscreenProgress.value,
+ cornerRadius,
+ fullscreenCornerRadius
+ ) / inheritedScale
+
companion object {
private val CLEAR_PAINT =
Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
index 9925873c7d..71bc865f85 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
@@ -16,20 +16,32 @@
package com.android.quickstep.task.thumbnail
+import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
+import com.android.quickstep.task.viewmodel.TaskViewData
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
-class TaskThumbnailViewModel {
- private val _uiState: MutableStateFlow =
- MutableStateFlow(TaskThumbnailUiState.Uninitialized)
- val uiState: StateFlow = _uiState
+class TaskThumbnailViewModel(recentsViewData: RecentsViewData, taskViewData: TaskViewData) {
+ private val task = MutableStateFlow(null)
+
+ val recentsFullscreenProgress = recentsViewData.fullscreenProgress
+ val inheritedScale =
+ combine(recentsViewData.scale, taskViewData.scale) { recentsScale, taskScale ->
+ recentsScale * taskScale
+ }
+ val uiState =
+ task.map { taskVal ->
+ when {
+ taskVal == null -> Uninitialized
+ taskVal.isRunning -> LiveTile
+ else -> Uninitialized
+ }
+ }
fun bind(task: TaskThumbnail) {
- _uiState.value =
- if (task.isRunning) {
- TaskThumbnailUiState.LiveTile
- } else {
- TaskThumbnailUiState.Uninitialized
- }
+ this.task.value = task
}
}
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
new file mode 100644
index 0000000000..a8b5112860
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.task.viewmodel
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class TaskViewData {
+ // This is typically a View concern but it is used to invalidate rendering in other Views
+ val scale = MutableStateFlow(1f)
+}
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index 5c5ee7ed57..770a4525cf 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -116,9 +116,9 @@ public class AppPairsController {
*/
public void saveAppPair(GroupedTaskView gtv) {
InteractionJankMonitorWrapper.begin(gtv, Cuj.CUJ_LAUNCHER_SAVE_APP_PAIR);
- TaskView.TaskContainer[] containers = gtv.getTaskContainers();
- WorkspaceItemInfo recentsInfo1 = containers[0].getItemInfo();
- WorkspaceItemInfo recentsInfo2 = containers[1].getItemInfo();
+ List containers = gtv.getTaskContainers();
+ WorkspaceItemInfo recentsInfo1 = containers.get(0).getItemInfo();
+ WorkspaceItemInfo recentsInfo2 = containers.get(1).getItemInfo();
WorkspaceItemInfo app1 = lookupLaunchableItem(recentsInfo1.getComponentKey());
WorkspaceItemInfo app2 = lookupLaunchableItem(recentsInfo2.getComponentKey());
diff --git a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
index 544c64d3da..d36dc7e754 100644
--- a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
+++ b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
@@ -48,12 +48,14 @@ class DeviceConfigHelper(private val factory: (PropReader) -> Config
PropReader(
object : PropProvider {
override fun get(key: String, fallback: T): T {
- if (fallback is Int)
+ if (fallback is Int) {
+ allKeys.add(key)
return DeviceConfig.getInt(NAMESPACE_LAUNCHER, key, fallback) as T
- else if (fallback is Boolean)
+ } else if (fallback is Boolean) {
+ allKeys.add(key)
return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, fallback)
as T
- else return fallback
+ } else return fallback
}
}
)
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 5968901787..57bc2d78ba 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -16,7 +16,7 @@
package com.android.quickstep.views;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
@@ -42,6 +42,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.desktop.DesktopRecentsTransitionController;
import com.android.launcher3.util.CancellableTask;
import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.ViewPool;
import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskThumbnailCache;
@@ -69,8 +70,6 @@ public class DesktopTaskView extends TaskView {
private static final boolean DEBUG = false;
- private final ArrayList mSnapshotViews = new ArrayList<>();
-
private final ArrayList> mPendingThumbnailRequests = new ArrayList<>();
private final TaskView.FullscreenDrawParams mSnapshotDrawParams;
@@ -81,6 +80,8 @@ public class DesktopTaskView extends TaskView {
private final PointF mTempPointF = new PointF();
+ private final ViewPool mTaskthumbnailViewPool;
+
public DesktopTaskView(Context context) {
this(context, null);
}
@@ -103,6 +104,10 @@ public class DesktopTaskView extends TaskView {
return QuickStepContract.getWindowCornerRadius(context);
}
};
+ // As DesktopTaskView is inflated in background, use initialSize=0 to avoid initPool.
+ mTaskthumbnailViewPool = new ViewPool<>(context, this, R.layout.task_thumbnail,
+ /* maxSize= */10, /* initialSize= */ 0);
+ mTaskContainers = new ArrayList<>();
}
@Override
@@ -163,45 +168,36 @@ public class DesktopTaskView extends TaskView {
}
cancelPendingLoadTasks();
- mTaskContainers = new TaskContainer[tasks.size()];
-
- // Ensure there are equal number of snapshot views and tasks.
- // More tasks than views, add views. More views than tasks, remove views.
- // TODO(b/251586230): use a ViewPool for creating TaskThumbnailViews
- if (mSnapshotViews.size() > tasks.size()) {
- int diff = mSnapshotViews.size() - tasks.size();
- for (int i = 0; i < diff; i++) {
- TaskThumbnailViewDeprecated snapshotView = mSnapshotViews.remove(0);
- removeView(snapshotView);
- }
- } else if (mSnapshotViews.size() < tasks.size()) {
- int diff = tasks.size() - mSnapshotViews.size();
- for (int i = 0; i < diff; i++) {
- TaskThumbnailViewDeprecated snapshotView =
- new TaskThumbnailViewDeprecated(getContext());
- mSnapshotViews.add(snapshotView);
- // Add snapshots from to position after the initial child views.
- addView(snapshotView, mChildCountAtInflation,
- new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- }
- }
-
+ ((ArrayList) mTaskContainers).ensureCapacity(tasks.size());
for (int i = 0; i < tasks.size(); i++) {
Task task = tasks.get(i);
- TaskThumbnailViewDeprecated thumbnailView = mSnapshotViews.get(i);
+ TaskThumbnailViewDeprecated thumbnailView;
+ if (i >= mTaskContainers.size()) {
+ thumbnailView = mTaskthumbnailViewPool.getView();
+ // Add thumbnailView from to position after the initial child views.
+ addView(thumbnailView, mChildCountAtInflation,
+ new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
+ } else {
+ thumbnailView = mTaskContainers.get(i).getThumbnailView();
+ }
thumbnailView.bind(task);
- mTaskContainers[i] = createAttributeContainer(task, thumbnailView);
+ TaskContainer taskContainer = new TaskContainer(task, thumbnailView, mIconView,
+ STAGE_POSITION_UNDEFINED, /*digitalWellBeingToast=*/ null);
+ if (i >= mTaskContainers.size()) {
+ mTaskContainers.add(taskContainer);
+ } else {
+ mTaskContainers.set(i, taskContainer);
+ }
+ }
+ while (mTaskContainers.size() > tasks.size()) {
+ TaskContainer taskContainer = mTaskContainers.remove(mTaskContainers.size() - 1);
+ removeView(taskContainer.getThumbnailView());
+ mTaskthumbnailViewPool.recycle(taskContainer.getThumbnailView());
}
setOrientationState(orientedState);
}
- private TaskContainer createAttributeContainer(Task task,
- TaskThumbnailViewDeprecated thumbnailView) {
- return new TaskContainer(task, thumbnailView, mIconView,
- STAGE_POSITION_UNDEFINED, /*digitalWellBeingToast=*/ null);
- }
-
@Override
public void onTaskListVisibilityChanged(boolean visible, int changes) {
cancelPendingLoadTasks();
@@ -314,7 +310,7 @@ public class DesktopTaskView extends TaskView {
int thumbnailTopMarginPx = mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
containerHeight -= thumbnailTopMarginPx;
- if (mTaskContainers.length == 0) {
+ if (mTaskContainers.isEmpty()) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index c26fc0c342..1b4d22fc2e 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -98,7 +98,7 @@ public class GroupedTaskView extends TaskView {
@Deprecated
@Nullable
private Task getSecondTask() {
- return mTaskContainers.length > 1 ? mTaskContainers[1].getTask() : null;
+ return mTaskContainers.size() > 1 ? mTaskContainers.get(1).getTask() : null;
}
@Override
@@ -150,11 +150,11 @@ public class GroupedTaskView extends TaskView {
public void bind(Task primary, Task secondary, RecentsOrientedState orientedState,
@Nullable SplitBounds splitBoundsConfig) {
super.bind(primary, orientedState);
- mTaskContainers = new TaskContainer[]{
- mTaskContainers[0],
+ mTaskContainers = Arrays.asList(
+ mTaskContainers.get(0),
new TaskContainer(secondary, findViewById(R.id.bottomright_snapshot),
- mIconView2, STAGE_POSITION_BOTTOM_OR_RIGHT, mDigitalWellBeingToast2)};
- mTaskContainers[0].setStagePosition(
+ mIconView2, STAGE_POSITION_BOTTOM_OR_RIGHT, mDigitalWellBeingToast2));
+ mTaskContainers.get(0).setStagePosition(
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT);
mSnapshotView2.bind(secondary);
mSplitBoundsConfig = splitBoundsConfig;
@@ -176,12 +176,12 @@ public class GroupedTaskView extends TaskView {
public void setUpShowAllInstancesListener() {
// sets up the listener for the left/top task
super.setUpShowAllInstancesListener();
- if (mTaskContainers.length < 2) {
+ if (mTaskContainers.size() < 2) {
return;
}
// right/bottom task's base package name
- String taskPackageName = mTaskContainers[1].getTask().key.getPackageName();
+ String taskPackageName = mTaskContainers.get(1).getTask().key.getPackageName();
// icon of the right/bottom task
View showWindowsView = findViewById(R.id.show_windows_right);
@@ -279,7 +279,7 @@ public class GroupedTaskView extends TaskView {
@Nullable
@Override
public RunnableList launchTaskAnimated() {
- if (mTaskContainers.length == 0) {
+ if (mTaskContainers.isEmpty()) {
return null;
}
@@ -407,9 +407,8 @@ public class GroupedTaskView extends TaskView {
} else {
// Currently being split with this taskView, let the non-split selected thumbnail
// take up full thumbnail area
- Optional nonSplitContainer = Arrays.stream(
- mTaskContainers).filter(
- container -> container.getTask().key.id != initSplitTaskId).findAny();
+ Optional nonSplitContainer = mTaskContainers.stream().filter(
+ container -> container.getTask().key.id != initSplitTaskId).findAny();
nonSplitContainer.ifPresent(
taskIdAttributeContainer -> taskIdAttributeContainer.getThumbnailView().measure(
widthMeasureSpec, MeasureSpec.makeMeasureSpec(
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 5188d4a0a3..8a917d68bf 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -33,9 +34,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.NavigationMode;
import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
@@ -43,12 +42,26 @@ import com.android.quickstep.util.LayoutUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.function.Consumer;
/**
* View for showing action buttons in Overview
*/
public class OverviewActionsView extends FrameLayout
implements OnClickListener, Insettable {
+ public static final FloatProperty> FLOAT_SETTER =
+ new FloatProperty<>("floatSetter") {
+ @Override
+ public void setValue(Consumer consumer, float v) {
+ consumer.accept(v);
+ }
+
+ @Override
+ public Float get(Consumer consumer) {
+ return -1f;
+ }
+ };
private final Rect mInsets = new Rect();
@@ -89,30 +102,24 @@ public class OverviewActionsView extends FrameLayo
private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3;
private static final int INDEX_SHARE_TARGET_ALPHA = 4;
private static final int INDEX_SCROLL_ALPHA = 5;
- private static final int NUM_ALPHAS = 6;
-
- public @interface ScreenshotButtonHiddenFlags { }
- public static final int FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT = 1 << 0;
+ private static final int INDEX_GROUPED_ALPHA = 6;
+ private static final int INDEX_3P_LAUNCHER = 7;
+ private static final int NUM_ALPHAS = 8;
public @interface SplitButtonHiddenFlags { }
public static final int FLAG_SMALL_SCREEN_HIDE_SPLIT = 1 << 0;
- public static final int FLAG_MULTIPLE_TASKS_HIDE_SPLIT = 1 << 1;
- public @interface SplitButtonDisabledFlags { }
- public static final int FLAG_SINGLE_TASK_DISABLE_SPLIT = 1 << 0;
-
- public @interface AppPairButtonHiddenFlags { }
- public static final int FLAG_SINGLE_TASK_HIDE_APP_PAIR = 1 << 0;
- public static final int FLAG_SMALL_SCREEN_HIDE_APP_PAIR = 1 << 1;
- public static final int FLAG_3P_LAUNCHER_HIDE_APP_PAIR = 1 << 2;
-
- private MultiValueAlpha mMultiValueAlpha;
+ /** Holds MultiValueAlpha values for all actions buttons */
+ private final MultiValueAlpha[] mMultiValueAlphas = new MultiValueAlpha[2];
+ /** Index used for single-task actions in the mMultiValueAlphas array */
+ private static final int ACTIONS_ALPHAS = 0;
+ /** Index used for grouped-task actions in the mMultiValueAlphas array */
+ private static final int GROUP_ACTIONS_ALPHAS = 1;
+ /** Container for the action buttons below a focused, non-split Overview tile. */
protected LinearLayout mActionButtons;
- // The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is an
- // ImageButton in go launcher (does not share a common class with Button). Take care when
- // casting this.
- private View mScreenshotButton;
+ /** Container for the action buttons below a focused, split Overview tile. */
+ protected LinearLayout mGroupActionButtons;
private Button mSplitButton;
private Button mSaveAppPairButton;
@@ -122,21 +129,16 @@ public class OverviewActionsView extends FrameLayo
@ActionsDisabledFlags
protected int mDisabledFlags;
- @ScreenshotButtonHiddenFlags
- private int mScreenshotButtonHiddenFlags;
-
@SplitButtonHiddenFlags
private int mSplitButtonHiddenFlags;
- @AppPairButtonHiddenFlags
- private int mAppPairButtonHiddenFlags;
-
@Nullable
protected T mCallbacks;
@Nullable
protected DeviceProfile mDp;
private final Rect mTaskSize = new Rect();
+ private boolean mIsGroupedTask = false;
public OverviewActionsView(Context context) {
this(context, null);
@@ -153,12 +155,21 @@ public class OverviewActionsView extends FrameLayo
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ // Initialize 2 view containers: one for single tasks, one for grouped tasks.
+ // These will take up the same space on the screen and alternate visibility as needed.
mActionButtons = findViewById(R.id.action_buttons);
- mMultiValueAlpha = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
- mMultiValueAlpha.setUpdateVisibility(true);
+ mGroupActionButtons = findViewById(R.id.group_action_buttons);
+ // Initialize a list to set alpha on mActionButtons and mGroupActionButtons simultaneously.
+ mMultiValueAlphas[ACTIONS_ALPHAS] = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
+ mMultiValueAlphas[GROUP_ACTIONS_ALPHAS] =
+ new MultiValueAlpha(mGroupActionButtons, NUM_ALPHAS);
+ Arrays.stream(mMultiValueAlphas).forEach(a -> a.setUpdateVisibility(true));
- mScreenshotButton = findViewById(R.id.action_screenshot);
- mScreenshotButton.setOnClickListener(this);
+ // The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is
+ // an ImageButton in go launcher (does not share a common class with Button). Take care when
+ // casting this.
+ View screenshotButton = findViewById(R.id.action_screenshot);
+ screenshotButton.setOnClickListener(this);
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
mSaveAppPairButton = findViewById(R.id.action_save_app_pair);
@@ -209,7 +220,7 @@ public class OverviewActionsView extends FrameLayo
mHiddenFlags &= ~visibilityFlags;
}
boolean isHidden = mHiddenFlags != 0;
- mMultiValueAlpha.get(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1);
+ setActionsAlpha(INDEX_HIDDEN_FLAGS_ALPHA, isHidden ? 0 : 1);
}
/**
@@ -236,12 +247,8 @@ public class OverviewActionsView extends FrameLayo
* @param isGroupedTask True if the focused task is a grouped task.
*/
public void updateForGroupedTask(boolean isGroupedTask) {
- // Update flags to see if split button should be hidden.
- updateSplitButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SPLIT, isGroupedTask);
- // Update flags to see if screenshot button should be hidden.
- updateScreenshotButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT, isGroupedTask);
- // Update flags to see if save app pair button should be hidden.
- updateAppPairButtonHiddenFlags(FLAG_SINGLE_TASK_HIDE_APP_PAIR, !isGroupedTask);
+ mIsGroupedTask = isGroupedTask;
+ updateActionButtonsVisibility();
}
/**
@@ -251,36 +258,30 @@ public class OverviewActionsView extends FrameLayo
assert mDp != null;
// Update flags to see if split button should be hidden.
updateSplitButtonHiddenFlags(FLAG_SMALL_SCREEN_HIDE_SPLIT, !mDp.isTablet);
- // Update flags to see if save app pair button should be hidden.
- updateAppPairButtonHiddenFlags(FLAG_SMALL_SCREEN_HIDE_APP_PAIR, !mDp.isTablet);
+ updateActionButtonsVisibility();
+ }
+
+ private void updateActionButtonsVisibility() {
+ assert mDp != null;
+ boolean showSingleTaskActions = !mIsGroupedTask;
+ boolean showGroupActions = mIsGroupedTask && mDp.isTablet;
+ getActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showSingleTaskActions ? 1 : 0);
+ getGroupActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showGroupActions ? 1 : 0);
}
/**
* Updates flags to hide and show actions buttons for 1p/3p launchers.
*/
public void updateFor3pLauncher(boolean is3pLauncher) {
- updateAppPairButtonHiddenFlags(FLAG_3P_LAUNCHER_HIDE_APP_PAIR, is3pLauncher);
+ getGroupActionsAlphas().get(INDEX_3P_LAUNCHER).setValue(is3pLauncher ? 0 : 1);
}
- /**
- * Updates the proper flags to indicate whether the "Screenshot" button should be hidden.
- *
- * @param flag The flag to update.
- * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
- */
- private void updateScreenshotButtonHiddenFlags(@ScreenshotButtonHiddenFlags int flag,
- boolean enable) {
- if (mScreenshotButton == null) return;
- if (enable) {
- mScreenshotButtonHiddenFlags |= flag;
- } else {
- mScreenshotButtonHiddenFlags &= ~flag;
- }
- int desiredVisibility = mScreenshotButtonHiddenFlags == 0 ? VISIBLE : GONE;
- if (mScreenshotButton.getVisibility() != desiredVisibility) {
- mScreenshotButton.setVisibility(desiredVisibility);
- mActionButtons.requestLayout();
- }
+ private MultiValueAlpha getActionsAlphas() {
+ return mMultiValueAlphas[ACTIONS_ALPHAS];
+ }
+
+ private MultiValueAlpha getGroupActionsAlphas() {
+ return mMultiValueAlphas[GROUP_ACTIONS_ALPHAS];
}
/**
@@ -304,56 +305,36 @@ public class OverviewActionsView extends FrameLayo
}
}
- /**
- * Updates the proper flags to indicate whether the "Save app pair" button should be disabled.
- *
- * @param flag The flag to update.
- * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
- */
- private void updateAppPairButtonHiddenFlags(
- @AppPairButtonHiddenFlags int flag, boolean enable) {
- if (!FeatureFlags.enableAppPairs()) {
- return;
- }
-
- if (mSaveAppPairButton == null) return;
- if (enable) {
- mAppPairButtonHiddenFlags |= flag;
- } else {
- mAppPairButtonHiddenFlags &= ~flag;
- }
- int desiredVisibility = mAppPairButtonHiddenFlags == 0 ? VISIBLE : GONE;
- if (mSaveAppPairButton.getVisibility() != desiredVisibility) {
- mSaveAppPairButton.setVisibility(desiredVisibility);
- mActionButtons.requestLayout();
- }
+ private void setActionsAlpha(int index, float value) {
+ Arrays.stream(mMultiValueAlphas).forEach(a -> a.get(index).setValue(value));
}
- public MultiProperty getContentAlpha() {
- return mMultiValueAlpha.get(INDEX_CONTENT_ALPHA);
+ public Consumer getContentAlphaSetter() {
+ return v -> setActionsAlpha(INDEX_CONTENT_ALPHA, v);
}
- public MultiProperty getVisibilityAlpha() {
- return mMultiValueAlpha.get(INDEX_VISIBILITY_ALPHA);
+ public Consumer getVisibilityAlphaSetter() {
+ return v -> setActionsAlpha(INDEX_VISIBILITY_ALPHA, v);
}
- public MultiProperty getFullscreenAlpha() {
- return mMultiValueAlpha.get(INDEX_FULLSCREEN_ALPHA);
+ public Consumer getFullscreenAlphaSetter() {
+ return v -> setActionsAlpha(INDEX_FULLSCREEN_ALPHA, v);
}
- public MultiProperty getShareTargetAlpha() {
- return mMultiValueAlpha.get(INDEX_SHARE_TARGET_ALPHA);
+ public Consumer getShareTargetAlphaSetter() {
+ return v -> setActionsAlpha(INDEX_SHARE_TARGET_ALPHA, v);
}
- public MultiProperty getIndexScrollAlpha() {
- return mMultiValueAlpha.get(INDEX_SCROLL_ALPHA);
+ public Consumer getIndexScrollAlphaSetter() {
+ return v -> setActionsAlpha(INDEX_SCROLL_ALPHA, v);
}
/**
* Returns the visibility of the overview actions buttons.
*/
- public @Visibility int getActionsButtonVisibility() {
- return mActionButtons.getVisibility();
+ public boolean areActionsButtonsVisible() {
+ return mActionButtons.getVisibility() == View.VISIBLE
+ || mGroupActionButtons.getVisibility() == View.VISIBLE;
}
/**
@@ -366,10 +347,17 @@ public class OverviewActionsView extends FrameLayo
/** Updates vertical margins for different navigation mode or configuration changes. */
public void updateVerticalMargin(NavigationMode mode) {
+ updateActionBarPosition(mActionButtons);
+ updateActionBarPosition(mGroupActionButtons);
+ }
+
+ /** Positions actions buttons according to device settings and insets. */
+ private void updateActionBarPosition(LinearLayout actionBar) {
if (mDp == null) {
return;
}
- LayoutParams actionParams = (LayoutParams) mActionButtons.getLayoutParams();
+
+ LayoutParams actionParams = (LayoutParams) actionBar.getLayoutParams();
actionParams.setMargins(
actionParams.leftMargin, mDp.overviewActionsTopMarginPx,
actionParams.rightMargin, getBottomMargin());
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 075f159d10..4431d62c5f 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -35,6 +35,7 @@ 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.enableGridOnlyOverview;
+import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
@@ -186,6 +187,7 @@ import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.ViewUtils;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.recents.viewmodel.RecentsViewData;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.AnimUtils;
@@ -376,6 +378,9 @@ public abstract class RecentsView() {
@@ -446,6 +451,8 @@ public abstract class RecentsView mSizeStrategy;
@Nullable
@@ -2012,6 +2019,9 @@ public abstract class RecentsView containers = taskView.getTaskContainers();
+ if (containers.isEmpty()) {
continue;
}
int index = indexOfChild(taskView);
@@ -2367,7 +2377,7 @@ public abstract class RecentsView tasksToUpdate = Arrays.stream(containers).filter(Objects::nonNull)
+ List tasksToUpdate = containers.stream()
.map(TaskContainer::getTask)
.collect(Collectors.toCollection(ArrayList::new));
if (mTmpRunningTasks != null) {
@@ -4295,7 +4305,7 @@ public abstract class RecentsView 0) {
setVisibility(VISIBLE);
@@ -4801,7 +4811,7 @@ public abstract class RecentsView TEMP_PARAMS =
new MainThreadInitializedObject<>(FullscreenDrawParams::new);
@@ -606,4 +607,9 @@ public class TaskThumbnailViewDeprecated extends View {
}
return mThumbnailData.isRealSnapshot && !mTask.isLocked;
}
+
+ @Override
+ public void onRecycle() {
+ // Do nothing
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 4046a89f5f..65a8c771e8 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -107,6 +107,7 @@ import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.quickstep.task.thumbnail.TaskThumbnail;
import com.android.quickstep.task.thumbnail.TaskThumbnailView;
+import com.android.quickstep.task.viewmodel.TaskViewData;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.BorderAnimator;
import com.android.quickstep.util.RecentsOrientedState;
@@ -326,6 +327,7 @@ public class TaskView extends FrameLayout implements Reusable {
}
};
+ public TaskViewData mTaskViewData = new TaskViewData();
protected TaskThumbnailViewDeprecated mTaskThumbnailViewDeprecated;
protected TaskThumbnailView mTaskThumbnailView;
protected TaskViewIcon mIconView;
@@ -368,7 +370,7 @@ public class TaskView extends FrameLayout implements Reusable {
private float mStableAlpha = 1;
private int mTaskViewId = -1;
- protected TaskContainer[] mTaskContainers = new TaskContainer[0];
+ protected List mTaskContainers = Collections.emptyList();
private boolean mShowScreenshot;
private boolean mBorderEnabled;
@@ -496,7 +498,7 @@ public class TaskView extends FrameLayout implements Reusable {
public void notifyIsRunningTaskUpdated() {
// TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
// so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
- if (mTaskContainers.length > 0) {
+ if (!mTaskContainers.isEmpty()) {
bindTaskThumbnailView();
}
}
@@ -685,9 +687,9 @@ public class TaskView extends FrameLayout implements Reusable {
*/
public void bind(Task task, RecentsOrientedState orientedState) {
cancelPendingLoadTasks();
- mTaskContainers = new TaskContainer[]{
+ mTaskContainers = Collections.singletonList(
new TaskContainer(task, mTaskThumbnailViewDeprecated, mIconView,
- STAGE_POSITION_UNDEFINED, mDigitalWellBeingToast)};
+ STAGE_POSITION_UNDEFINED, mDigitalWellBeingToast));
if (enableRefactorTaskThumbnail()) {
bindTaskThumbnailView();
} else {
@@ -706,10 +708,10 @@ public class TaskView extends FrameLayout implements Reusable {
* Sets up an on-click listener and the visibility for show_windows icon on top of the task.
*/
public void setUpShowAllInstancesListener() {
- if (mTaskContainers.length == 0) {
+ if (mTaskContainers.isEmpty()) {
return;
}
- String taskPackageName = mTaskContainers[0].getTask().key.getPackageName();
+ String taskPackageName = mTaskContainers.get(0).getTask().key.getPackageName();
// icon of the top/left task
View showWindowsView = findViewById(R.id.show_windows);
@@ -752,9 +754,9 @@ public class TaskView extends FrameLayout implements Reusable {
}
/**
- * Returns an array of all TaskContainers in the TaskView.
+ * Returns a list of all TaskContainers in the TaskView.
*/
- public TaskContainer[] getTaskContainers() {
+ public List getTaskContainers() {
return mTaskContainers;
}
@@ -766,7 +768,7 @@ public class TaskView extends FrameLayout implements Reusable {
@Deprecated
@Nullable
public Task getFirstTask() {
- return mTaskContainers.length > 0 ? mTaskContainers[0].getTask() : null;
+ return !mTaskContainers.isEmpty() ? mTaskContainers.get(0).getTask() : null;
}
/**
@@ -780,12 +782,12 @@ public class TaskView extends FrameLayout implements Reusable {
* Returns a copy of integer array containing taskIds of all tasks in the TaskView.
*/
public int[] getTaskIds() {
- return Arrays.stream(mTaskContainers).mapToInt(
+ return mTaskContainers.stream().mapToInt(
container -> container.getTask().key.id).toArray();
}
public boolean containsMultipleTasks() {
- return mTaskContainers.length > 1;
+ return mTaskContainers.size() > 1;
}
/**
@@ -794,7 +796,7 @@ public class TaskView extends FrameLayout implements Reusable {
*/
@Nullable
public TaskContainer getTaskContainerById(int taskId) {
- return Arrays.stream(mTaskContainers).filter(
+ return mTaskContainers.stream().filter(
container -> container.getTask().key.id == taskId).findFirst().orElse(null);
}
@@ -805,7 +807,7 @@ public class TaskView extends FrameLayout implements Reusable {
*/
@Deprecated
public TaskThumbnailViewDeprecated getFirstThumbnailView() {
- return mTaskContainers.length > 0 ? mTaskContainers[0].getThumbnailView()
+ return !mTaskContainers.isEmpty() ? mTaskContainers.get(0).getThumbnailView()
: mTaskThumbnailViewDeprecated;
}
@@ -826,7 +828,7 @@ public class TaskView extends FrameLayout implements Reusable {
}
public TaskThumbnailViewDeprecated[] getThumbnailViews() {
- return Arrays.stream(mTaskContainers).map(
+ return mTaskContainers.stream().map(
TaskContainer::getThumbnailView).toArray(
TaskThumbnailViewDeprecated[]::new);
}
@@ -839,7 +841,7 @@ public class TaskView extends FrameLayout implements Reusable {
@Deprecated
@Nullable
public TaskViewIcon getFirstIconView() {
- return mTaskContainers.length > 0 ? mTaskContainers[0].getIconView() : null;
+ return !mTaskContainers.isEmpty() ? mTaskContainers.get(0).getIconView() : null;
}
@Override
@@ -892,10 +894,10 @@ public class TaskView extends FrameLayout implements Reusable {
*/
protected boolean confirmSecondSplitSelectApp() {
int index = getLastSelectedChildTaskIndex();
- if (index >= mTaskContainers.length) {
+ if (index >= mTaskContainers.size()) {
return false;
}
- TaskContainer container = mTaskContainers[index];
+ TaskContainer container = mTaskContainers.get(index);
if (container != null) {
return getRecentsView().confirmSplitSelect(this, container.getTask(),
container.getIconView().getDrawable(), container.getThumbnailView(),
@@ -1217,9 +1219,8 @@ public class TaskView extends FrameLayout implements Reusable {
}
protected boolean showTaskMenuWithContainer(TaskViewIcon iconView) {
- Optional menuContainer = Arrays.stream(
- mTaskContainers).filter(
- container -> container.getIconView() == iconView).findAny();
+ Optional menuContainer = mTaskContainers.stream().filter(
+ container -> container.getIconView() == iconView).findAny();
if (menuContainer.isEmpty()) {
return false;
}
@@ -1462,6 +1463,9 @@ public class TaskView extends FrameLayout implements Reusable {
scale *= mDismissScale;
setScaleX(scale);
setScaleY(scale);
+ if (enableRefactorTaskThumbnail()) {
+ mTaskViewData.getScale().setValue(scale);
+ }
updateSnapshotRadius();
}
@@ -1768,10 +1772,7 @@ public class TaskView extends FrameLayout implements Reusable {
progress = Utilities.boundToRange(progress, 0, 1);
mFullscreenProgress = progress;
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334826840) Add corner rounding to new TTV
- mTaskThumbnailViewDeprecated.getTaskOverlay().setFullscreenProgress(progress);
- }
+ mTaskThumbnailViewDeprecated.getTaskOverlay().setFullscreenProgress(progress);
RecentsView recentsView = mContainer.getOverviewPanel();
// Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
@@ -1785,10 +1786,7 @@ public class TaskView extends FrameLayout implements Reusable {
protected void updateSnapshotRadius() {
updateCurrentFullscreenParams();
- if (!enableRefactorTaskThumbnail()) {
- // TODO(b/334826840) Add corner rounding to new TTV
- mTaskThumbnailViewDeprecated.setFullscreenParams(mCurrentFullscreenParams);
- }
+ mTaskThumbnailViewDeprecated.setFullscreenParams(mCurrentFullscreenParams);
}
void updateCurrentFullscreenParams() {
@@ -1799,8 +1797,8 @@ public class TaskView extends FrameLayout implements Reusable {
if (getRecentsView() == null) {
return;
}
- fullscreenParams.setProgress(mFullscreenProgress, getRecentsView().getScaleX(),
- getScaleX());
+ fullscreenParams.setProgress(
+ mFullscreenProgress, getRecentsView().getScaleX(), getScaleX());
}
/**
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
index e71192fe33..efd7becf79 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
@@ -17,38 +17,63 @@
package com.android.quickstep.task.thumbnail
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.task.viewmodel.TaskViewData
import com.android.systemui.shared.recents.model.Task
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class TaskThumbnailViewModelTest {
- private val systemUnderTest = TaskThumbnailViewModel()
+ private val recentsViewData = RecentsViewData()
+ private val taskViewData = TaskViewData()
+ private val systemUnderTest = TaskThumbnailViewModel(recentsViewData, taskViewData)
@Test
- fun initialStateIsUninitialized() {
- assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.Uninitialized)
+ fun initialStateIsUninitialized() = runTest {
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.Uninitialized)
}
@Test
- fun bindRunningTask_thenStateIs_LiveTile() {
+ fun bindRunningTask_thenStateIs_LiveTile() = runTest {
val taskThumbnail = TaskThumbnail(Task(), isRunning = true)
systemUnderTest.bind(taskThumbnail)
- assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.LiveTile)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.LiveTile)
}
@Test
- fun bindRunningTaskThenStoppedTask_thenStateIs_Uninitialized() {
+ fun setRecentsFullscreenProgress_thenProgressIsPassedThrough() = runTest {
+ recentsViewData.fullscreenProgress.value = 0.5f
+
+ assertThat(systemUnderTest.recentsFullscreenProgress.first()).isEqualTo(0.5f)
+
+ recentsViewData.fullscreenProgress.value = 0.6f
+
+ assertThat(systemUnderTest.recentsFullscreenProgress.first()).isEqualTo(0.6f)
+ }
+
+ @Test
+ fun setAncestorScales_thenScaleIsCalculated() = runTest {
+ recentsViewData.scale.value = 0.5f
+ taskViewData.scale.value = 0.6f
+
+ assertThat(systemUnderTest.inheritedScale.first()).isEqualTo(0.3f)
+ }
+
+ @Test
+ fun bindRunningTaskThenStoppedTask_thenStateIs_Uninitialized() = runTest {
// TODO(b/334825222): Change the expectation here when snapshot state is implemented
val task = Task()
val runningTask = TaskThumbnail(task, isRunning = true)
val stoppedTask = TaskThumbnail(task, isRunning = false)
systemUnderTest.bind(runningTask)
- assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.LiveTile)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.LiveTile)
systemUnderTest.bind(stoppedTask)
- assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.Uninitialized)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(TaskThumbnailUiState.Uninitialized)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
index c64ac23cc5..50f74c2cdf 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -35,6 +35,7 @@ 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,6 +168,7 @@ 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());
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index 2a54057724..bfd7bdba41 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -130,7 +130,7 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
.tapMenu()
.hasMenuItem("Save app pair"));
} else {
- overview.getOverviewActions().assertHasAction("Save app pair");
+ overview.getOverviewGroupActions().assertHasAction("Save app pair");
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
index eb20de2810..f29df613cd 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
@@ -91,7 +91,7 @@ class SplitAnimationControllerTest {
whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)
- whenever(mockTaskView.taskContainers).thenReturn(Array(1) { mockTaskContainer })
+ whenever(mockTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer })
whenever(splitSelectSource.drawable).thenReturn(mockSplitSourceDrawable)
whenever(splitSelectSource.view).thenReturn(mockSplitSourceView)
@@ -184,7 +184,7 @@ class SplitAnimationControllerTest {
whenever(mockTask.getKey()).thenReturn(mockTaskKey)
whenever(mockTaskKey.getId()).thenReturn(taskId)
whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)
- whenever(mockGroupedTaskView.taskContainers).thenReturn(Array(1) { mockTaskContainer })
+ whenever(mockGroupedTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer })
val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
splitAnimationController.getFirstAnimInitViews(
{ mockGroupedTaskView },
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 28fb1190b6..8b693187f5 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -44,7 +44,7 @@
"Dodaj na početni ekran"
"Dodali ste vidžet %1$s na početni ekran"
"Predlozi"
- "Neophodne aplikacije"
+ "Osnovno"
"Novosti i časopisi"
"Zona za opuštanje"
"Zabava"
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index b05002dffe..736eaab66f 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -44,7 +44,7 @@
"Přidat na plochu"
"Widget %1$s byl přidán na plochu"
"Návrhy"
- "Základní"
+ "Nejdůležitější aplikace"
"Zprávy a časopisy"
"Vaše klidová zóna"
"Zábava"
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 4aaa44bb6f..623b183dae 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -48,7 +48,7 @@
"Noticias y revistas"
"Zona de descanso"
"Entretenimiento"
- "Social"
+ "Redes sociales"
"Salud y bienestar"
"Clima"
"Sugerencias para ti"
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index c91e510a1b..4df953a4c6 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -48,7 +48,7 @@
"Noticias y revistas"
"Tu zona de descanso"
"Entretenimiento"
- "Social"
+ "Redes sociales"
"Salud y actividad física"
"El tiempo"
"Sugerencias para ti"
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 4f6f121f73..4c72f00ffd 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -44,7 +44,7 @@
"Ajouter à l\'écran d\'accueil"
"Widget %1$s ajouté à l\'écran d\'accueil"
"Suggestions"
- "Les bases"
+ "Indispensables"
"Actualités et magazines"
"Votre espace détente"
"Divertissement"
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index b6af6b3df5..da6a7113a9 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -44,7 +44,7 @@
"Dodaj do ekranu głównego"
"Widżet %1$s został dodany do ekranu głównego"
"Sugestie"
- "Niezbędne"
+ "Najbardziej przydatne"
"Wiadomości i czasopisma"
"Strefa relaksu"
"Rozrywka"
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index bb82b677fb..9eaae37f7a 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -44,7 +44,7 @@
"Додај на почетни екран"
"Додали сте виџет %1$s на почетни екран"
"Предлози"
- "Неопходне апликације"
+ "Основно"
"Новости и часописи"
"Зона за опуштање"
"Забава"
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 2975e97e80..a18aab65c7 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -44,7 +44,7 @@
"添加到主屏幕"
"已将“%1$s”微件添加到主屏幕"
"建议"
- "必备"
+ "必备之选"
"新闻与杂志"
"您的休闲区"
"娱乐"
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index b9a62e25b2..42297089e1 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -70,6 +70,7 @@ import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewGroup;
import android.view.animation.Interpolator;
import androidx.annotation.ChecksSdkIntAtLeast;
@@ -104,6 +105,7 @@ import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -835,4 +837,27 @@ public final class Utilities {
// No-Op
}
}
+
+ /**
+ * Does a depth-first search through the View hierarchy starting at root, to find a view that
+ * matches the predicate. Returns null if no View was found. View has a findViewByPredicate
+ * member function but it is currently a @hide API.
+ */
+ @Nullable
+ public static T findViewByPredicate(@NonNull View root,
+ @NonNull Predicate predicate) {
+ if (predicate.test(root)) {
+ return (T) root;
+ }
+ if (root instanceof ViewGroup parent) {
+ int count = parent.getChildCount();
+ for (int i = 0; i < count; i++) {
+ View view = findViewByPredicate(parent.getChildAt(i), predicate);
+ if (view != null) {
+ return (T) view;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index eabacbf56e..13680846f9 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -17,6 +17,8 @@ package com.android.launcher3.widget;
import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.Flags.enableWidgetTapToAdd;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_ADD_BUTTON_TAP;
import android.content.Context;
@@ -42,6 +44,7 @@ import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
+import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -74,6 +77,7 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
private boolean mDisableNavBarScrim = false;
@Nullable private WidgetCell mWidgetCellWithAddButton = null;
+ @Nullable private WidgetItem mLastSelectedWidgetItem = null;
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
@@ -161,6 +165,11 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
}
mWidgetCellWithAddButton = mWidgetCellWithAddButton != wc ? wc : null;
+ if (mWidgetCellWithAddButton != null) {
+ mLastSelectedWidgetItem = mWidgetCellWithAddButton.getWidgetItem();
+ } else {
+ mLastSelectedWidgetItem = null;
+ }
} else {
mActivityContext.getItemOnClickListener().onClick(wc);
}
@@ -174,7 +183,8 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
}
/**
- * Click handler for tap to add button.
+ * Click handler for tap to add button. This handler assumes we are in the Launcher activity and
+ * should not be used when the widget sheet is displayed elsewhere.
*/
private void addWidget(@NonNull PendingAddItemInfo info) {
// Using a boolean flag here to make sure the callback is only run once. This should never
@@ -182,19 +192,23 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
// needed.
final AtomicBoolean hasRun = new AtomicBoolean(false);
addOnCloseListener(() -> {
- if (!hasRun.get()) {
- Launcher.getLauncher(mActivityContext).getAccessibilityDelegate().addToWorkspace(
- info, /*accessibility=*/ false,
+ if (hasRun.get()) return;
+ hasRun.set(true);
+
+ // Going to NORMAL state will also dismiss the All Apps view if it is showing.
+ Launcher launcher = Launcher.getLauncher(mActivityContext);
+ launcher.getStateManager().goToState(NORMAL, forSuccessCallback(() -> {
+ launcher.getAccessibilityDelegate().addToWorkspace(info,
+ /*accessibility=*/ false,
/*finishCallback=*/ (success) -> {
mActivityContext.getStatsLogManager()
.logger()
.withItemInfo(info)
.log(LAUNCHER_WIDGET_ADD_BUTTON_TAP);
});
- hasRun.set(true);
- }
+ }));
});
- handleClose(true);
+ close(/* animate= */ true);
}
/**
@@ -243,6 +257,14 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView
return 0;
}
+ /**
+ * Returns the component of the widget that is currently showing an add button, if any.
+ */
+ @Nullable
+ protected WidgetItem getLastSelectedWidgetItem() {
+ return mLastSelectedWidgetItem;
+ }
+
@Override
public boolean onLongClick(View v) {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Widgets.onLongClick");
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 5dacfb0b23..eac2ce716a 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -503,6 +503,15 @@ public class WidgetCell extends LinearLayout {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+
+ if (changed && isShowingAddButton()) {
+ post(this::setupIconOrTextButton);
+ }
+ }
+
/**
* Loads a high resolution package icon to show next to the widget title.
*/
@@ -627,4 +636,19 @@ public class WidgetCell extends LinearLayout {
set.playSequentially(hideAnim, showAnim);
set.start();
}
+
+ /**
+ * Returns true if this WidgetCell is displaying the same item as info.
+ */
+ public boolean matchesItem(WidgetItem info) {
+ if (info == null || mItem == null) return false;
+ if (info.widgetInfo != null && mItem.widgetInfo != null) {
+ return info.widgetInfo.getUser().equals(mItem.widgetInfo.getUser())
+ && info.widgetInfo.getComponent().equals(mItem.widgetInfo.getComponent());
+ } else if (info.activityInfo != null && mItem.activityInfo != null) {
+ return info.activityInfo.getUser().equals(mItem.activityInfo.getUser())
+ && info.activityInfo.getComponent().equals(mItem.activityInfo.getComponent());
+ }
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index b4c4623029..4ea24265c3 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -142,6 +142,9 @@ public class WidgetsBottomSheet extends BaseWidgetSheet {
row.forEach(widgetItem -> {
WidgetCell widget = addItemCell(tableRow);
widget.applyFromCellItem(widgetItem);
+ if (widget.matchesItem(getLastSelectedWidgetItem())) {
+ widget.callOnClick();
+ }
});
widgetsTable.addView(tableRow);
});
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index 5292ee2db9..9c4db60f69 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -29,6 +29,7 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
@@ -40,6 +41,7 @@ import androidx.annotation.Px;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.recyclerview.ViewHolderBinder;
import com.android.launcher3.util.PackageUserKey;
@@ -194,15 +196,21 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
layoutParams.width = 0;
}
layoutParams.weight = layoutParams.width == 0 ? 0.33F : 0;
- leftPane.setLayoutParams(layoutParams);
- requestApplyInsets();
- if (mSelectedHeader != null) {
- if (mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey)) {
- mSuggestedWidgetsHeader.callOnClick();
- } else {
- getHeaderChangeListener().onHeaderChanged(mSelectedHeader);
+
+ post(() -> {
+ // The following calls all trigger requestLayout, so we post them to avoid
+ // calling requestLayout during a layout pass. This also fixes the related warnings
+ // in logcat.
+ leftPane.setLayoutParams(layoutParams);
+ requestApplyInsets();
+ if (mSelectedHeader != null) {
+ if (mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey)) {
+ mSuggestedWidgetsHeader.callOnClick();
+ } else {
+ getHeaderChangeListener().onHeaderChanged(mSelectedHeader);
+ }
}
- }
+ });
}
}
@@ -222,6 +230,9 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
if (mSuggestedWidgetsContainer == null && mRecommendedWidgetsCount > 0) {
setupSuggestedWidgets(LayoutInflater.from(getContext()));
mSuggestedWidgetsHeader.callOnClick();
+ } else if (mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey)) {
+ // Reselect widget if we are reloading recommendations while it is currently showing.
+ selectWidgetCell(mWidgetRecommendationsContainer, getLastSelectedWidgetItem());
}
}
@@ -269,6 +280,16 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
mRightPaneScrollView.setScrollY(0);
mRightPane.setAccessibilityPaneTitle(suggestionsRightPaneTitle);
mSuggestedWidgetsPackageUserKey = PackageUserKey.fromPackageItemInfo(packageItemInfo);
+ final boolean isChangingHeaders =
+ !mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey);
+ if (isChangingHeaders) {
+ // If switching from another header, unselect any WidgetCells. This is necessary
+ // because we do not clear/recycle the WidgetCells in the recommendations container
+ // when the header is clicked, only when onRecommendationsBound is called. That
+ // means a WidgetCell in the recommendations container may still be selected from
+ // the last time the recommendations were shown.
+ unselectWidgetCell(mWidgetRecommendationsContainer, getLastSelectedWidgetItem());
+ }
mSelectedHeader = mSuggestedWidgetsPackageUserKey;
});
mSuggestedWidgetsContainer.addView(mSuggestedWidgetsHeader);
@@ -357,6 +378,8 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
return new HeaderChangeListener() {
@Override
public void onHeaderChanged(@NonNull PackageUserKey selectedHeader) {
+ final boolean isSameHeader = mSelectedHeader != null
+ && mSelectedHeader.equals(selectedHeader);
mSelectedHeader = selectedHeader;
WidgetsListContentEntry contentEntry = mActivityContext.getPopupDataProvider()
.getSelectedAppWidgets(selectedHeader);
@@ -384,11 +407,20 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
contentEntryToBind,
ViewHolderBinder.POSITION_FIRST | ViewHolderBinder.POSITION_LAST,
Collections.EMPTY_LIST);
+ if (isSameHeader) {
+ // Reselect the last selected widget if we are reloading the same header.
+ selectWidgetCell(widgetsRowViewHolder.tableContainer,
+ getLastSelectedWidgetItem());
+ }
widgetsRowViewHolder.mDataCallback = data -> {
mWidgetsListTableViewHolderBinder.bindViewHolder(widgetsRowViewHolder,
contentEntryToBind,
ViewHolderBinder.POSITION_FIRST | ViewHolderBinder.POSITION_LAST,
Collections.singletonList(data));
+ if (isSameHeader) {
+ selectWidgetCell(widgetsRowViewHolder.tableContainer,
+ getLastSelectedWidgetItem());
+ }
};
mRightPane.removeAllViews();
mRightPane.addView(widgetsRowViewHolder.itemView);
@@ -401,6 +433,24 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
};
}
+ private static void selectWidgetCell(ViewGroup parent, WidgetItem item) {
+ if (parent == null || item == null) return;
+ WidgetCell cell = Utilities.findViewByPredicate(parent, v -> v instanceof WidgetCell wc
+ && wc.matchesItem(item));
+ if (cell != null && !cell.isShowingAddButton()) {
+ cell.callOnClick();
+ }
+ }
+
+ private static void unselectWidgetCell(ViewGroup parent, WidgetItem item) {
+ if (parent == null || item == null) return;
+ WidgetCell cell = Utilities.findViewByPredicate(parent, v -> v instanceof WidgetCell wc
+ && wc.matchesItem(item));
+ if (cell != null && cell.isShowingAddButton()) {
+ cell.hideAddButton(/* animate= */ false);
+ }
+ }
+
@Override
public void setInsets(Rect insets) {
super.setInsets(insets);
diff --git a/tests/Android.bp b/tests/Android.bp
index 5ec226353d..11177dee4e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -105,6 +105,7 @@ android_library {
android_library {
name: "Launcher3TestResources",
resource_dirs: ["res"],
+ asset_dirs: ["assets"],
// TODO(b/319712088): re-enable use_resource_processor
use_resource_processor: false,
}
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 74b3ccc0dd..4a04953bc1 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 OVERVIEW_OVER_HOME = "b/279059025";
public static final String UIOBJECT_STALE_ELEMENT = "b/319501259";
public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466";
- public static final String TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE = "b/326073471";
public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890";
public static final String ACTIVITY_NOT_RESUMED_AFTER_BACK = "b/322823209";
public static final String OVERVIEW_SELECT_TOOLTIP_MISALIGNED = "b/332485341";
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
diff --git a/tests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
similarity index 97%
rename from tests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
index 13dfd5eca8..c32461ea98 100644
--- a/tests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/HotseatReorderUnitTest.kt
@@ -22,6 +22,8 @@ import android.util.Log
import android.view.View
import androidx.core.view.get
import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
import com.android.launcher3.CellLayout
import com.android.launcher3.celllayout.board.CellLayoutBoard
import com.android.launcher3.celllayout.board.IconPoint
@@ -34,6 +36,7 @@ import java.util.Random
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
+import org.junit.runner.RunWith
private class HotseatReorderTestCase(
val startBoard: CellLayoutBoard,
@@ -44,6 +47,8 @@ private class HotseatReorderTestCase(
}
}
+@SmallTest
+@RunWith(AndroidJUnit4::class)
class HotseatReorderUnitTest {
private val applicationContext: Context =
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTestCase.java
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
similarity index 95%
rename from tests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
index 0bec1b2761..a9355ecb51 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderPreviewAnimationTest.kt
@@ -141,11 +141,14 @@ class ReorderPreviewAnimationTest {
ReorderPreviewAnimation.MODE_PREVIEW,
AnimationValues(dx = 0, dy = 0, scale = 100)
)
- testAnimationAtGivenProgress(
- PREVIEW_DURATION * 99,
- ReorderPreviewAnimation.MODE_PREVIEW,
- AnimationValues(dx = 5, dy = -10, scale = 96)
- )
+ // (b/339313407) Temporarily disable this test as the behavior is
+ // inconsistent between Soong & Gradle builds.
+ //
+ // testAnimationAtGivenProgress(
+ // PREVIEW_DURATION * 99,
+ // ReorderPreviewAnimation.MODE_PREVIEW,
+ // AnimationValues(dx = 5, dy = -10, scale = 96)
+ // )
testAnimationAtGivenProgress(
PREVIEW_DURATION * 98,
ReorderPreviewAnimation.MODE_PREVIEW,
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderTestCase.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderTestCase.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/ReorderTestCase.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/ReorderTestCase.java
diff --git a/tests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/UnitTestCellLayoutBuilderRule.kt
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/DeterministicRandomGenerator.kt
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/testgenerator/RandomMultiBoardGenerator.kt
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 68829e0dee..2e3944d666 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -358,6 +358,21 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
}
}
+ /**
+ * Gets Overview Actions specific to grouped tasks.
+ *
+ * @return The Overview group actions bar
+ */
+ @NonNull
+ public OverviewActions getOverviewGroupActions() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get overview group actions")) {
+ verifyActiveContainer();
+ UiObject2 groupActions = mLauncher.waitForOverviewObject("group_action_buttons");
+ return new OverviewActions(groupActions, mLauncher);
+ }
+ }
+
/**
* Returns if clear all button is visible.
*/
@@ -449,10 +464,18 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
private void verifyActionsViewVisibility() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to assert overview actions view visibility")) {
+ boolean isTablet = mLauncher.isTablet();
+ OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
+
if (isActionsViewVisible()) {
- mLauncher.waitForOverviewObject("action_buttons");
+ if (task.isTaskSplit()) {
+ mLauncher.waitForOverviewObject("group_action_buttons");
+ } else {
+ mLauncher.waitForOverviewObject("action_buttons");
+ }
} else {
mLauncher.waitUntilOverviewObjectGone("action_buttons");
+ mLauncher.waitUntilOverviewObjectGone("group_action_buttons");
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index aa8d33906b..68b0a36049 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -108,7 +108,7 @@ import java.util.stream.Collectors;
public final class LauncherInstrumentation {
private static final String TAG = "Tapl";
- private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 15;
+ private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 5;
private static final int GESTURE_STEP_MS = 16;
static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");