Merge "Demote unstable test testQuickSwitchFromApp from presubmit" into main
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index f72c556..e7b88dc 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -124,7 +124,8 @@
/** Type of popups that should get exclusive accessibility focus. */
public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_LISTENER
- & ~TYPE_ALL_APPS_EDU & ~TYPE_TASKBAR_ALL_APPS & ~TYPE_PIN_IME_POPUP;
+ & ~TYPE_ALL_APPS_EDU & ~TYPE_TASKBAR_ALL_APPS & ~TYPE_PIN_IME_POPUP
+ & ~TYPE_WIDGET_RESIZE_FRAME;
// These view all have particular operation associated with swipe down interaction.
public static final int TYPE_STATUS_BAR_SWIPE_DOWN_DISALLOW = TYPE_WIDGETS_BOTTOM_SHEET |
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 3655a19..c4ef4ae 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -425,7 +425,7 @@
}
/**
- * Only if actual text can be displayed in two line, the {@code true} value will be effective.
+ * Only if actual text can be displayed in two line, the {@code true} value will be effective.
*/
protected boolean shouldUseTwoLine() {
return FeatureFlags.enableTwolineAllapps() && isCurrentLanguageEnglish()
@@ -583,12 +583,12 @@
/**
* Find the appropriate text spacing to display the provided text
- * @param paint the paint used by the text view
- * @param text the text to display
- * @param allowedWidthPx available space to render the text
- * @param minSpacingEm minimum spacing allowed between characters
- * @return the final textSpacing value
*
+ * @param paint the paint used by the text view
+ * @param text the text to display
+ * @param allowedWidthPx available space to render the text
+ * @param minSpacingEm minimum spacing allowed between characters
+ * @return the final textSpacing value
* @see #setLetterSpacing(float)
*/
private float findBestSpacingValue(TextPaint paint, String text, float allowedWidthPx,
@@ -816,13 +816,13 @@
* iterating through the list of break points and determining if the strings between the break
* points can fit within the line it is in. We will show the modified string if there is enough
* horizontal and vertical space, otherwise this method will just return the original string.
- * Example assuming each character takes up one spot:
- * title = "Battery Stats", breakpoint = [6], stringPtr = 0, limitedWidth = 7
- * We get the current word -> from sublist(0, breakpoint[i]+1) so sublist (0,7) -> Battery,
- * now stringPtr = 7 then from sublist(7) the current string is " Stats" and the runningWidth
- * at this point exceeds limitedWidth and so we put " Stats" onto the next line (after checking
- * if the first char is a SPACE, we trim to append "Stats". So resulting string would be
- * "Battery\nStats"
+ * Example assuming each character takes up one spot:
+ * title = "Battery Stats", breakpoint = [6], stringPtr = 0, limitedWidth = 7
+ * We get the current word -> from sublist(0, breakpoint[i]+1) so sublist (0,7) -> Battery,
+ * now stringPtr = 7 then from sublist(7) the current string is " Stats" and the runningWidth
+ * at this point exceeds limitedWidth and so we put " Stats" onto the next line (after checking
+ * if the first char is a SPACE, we trim to append "Stats". So resulting string would be
+ * "Battery\nStats"
*/
public static CharSequence modifyTitleToSupportMultiLine(int limitedWidth, int limitedHeight,
CharSequence title, TextPaint paint, IntArray breakPoints, float spacingMultiplier,
@@ -836,25 +836,25 @@
StringBuilder newString = new StringBuilder();
paint.setLetterSpacing(MIN_LETTER_SPACING);
int stringPtr = 0;
- for (int i = 0; i < breakPoints.size()+1; i++) {
+ for (int i = 0; i < breakPoints.size() + 1; i++) {
if (i < breakPoints.size()) {
- currentWord = title.subSequence(stringPtr, breakPoints.get(i)+1);
+ currentWord = title.subSequence(stringPtr, breakPoints.get(i) + 1);
} else {
// last word from recent breakpoint until the end of the string
currentWord = title.subSequence(stringPtr, title.length());
}
- currentWordWidth = paint.measureText(currentWord,0, currentWord.length());
+ currentWordWidth = paint.measureText(currentWord, 0, currentWord.length());
runningWidth += currentWordWidth;
if (runningWidth <= limitedWidth) {
newString.append(currentWord);
} else {
- if (i != 0) {
+ if (i != 0) {
// If putting word onto a new line, make sure there is no space or new line
// character in the beginning of the current word and just put in the rest of
// the characters.
CharSequence lastCharacters = title.subSequence(stringPtr, title.length());
int beginningLetterType =
- Character.getType(Character.codePointAt(lastCharacters,0));
+ Character.getType(Character.codePointAt(lastCharacters, 0));
if (beginningLetterType == Character.SPACE_SEPARATOR
|| beginningLetterType == Character.LINE_SEPARATOR) {
lastCharacters = lastCharacters.length() > 1
@@ -875,7 +875,7 @@
// no need to look forward into the string if we've already finished processing
break;
}
- stringPtr = breakPoints.get(i)+1;
+ stringPtr = breakPoints.get(i) + 1;
}
return newString.toString();
}
@@ -965,12 +965,12 @@
return preloadDrawable;
}
- private boolean isIconDisabled(ItemInfoWithIcon info) {
- if (info.isArchived()) {
- return info.getProgressLevel() == 0
- && (info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0;
- }
- return info.getProgressLevel() == 0;
+ /**
+ * Returns true to grey the icon if the icon is either suspended or if the icon is pending
+ * download
+ */
+ public boolean isIconDisabled(ItemInfoWithIcon info) {
+ return info.isDisabled() || info.isPendingDownload();
}
public void applyDotState(ItemInfo itemInfo, boolean animate) {
@@ -1017,12 +1017,12 @@
if ((info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
setContentDescription(getContext()
.getString(
- R.string.app_installing_title, info.title, percentageString));
+ R.string.app_installing_title, info.title, percentageString));
} else if ((info.runtimeStatusFlags
& FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) {
setContentDescription(getContext()
.getString(
- R.string.app_downloading_title, info.title, percentageString));
+ R.string.app_downloading_title, info.title, percentageString));
}
}
}
@@ -1189,7 +1189,8 @@
public SafeCloseable prepareDrawDragView() {
resetIconScale();
setForceHideDot(true);
- return () -> { };
+ return () -> {
+ };
}
private void resetIconScale() {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 55416af..ca34dd1 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2226,8 +2226,7 @@
private Runnable getWidgetResizeFrameRunnable(DragOptions options,
LauncherAppWidgetHostView hostView, CellLayout cellLayout) {
AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
- if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE
- && !options.isAccessibleDrag) {
+ if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
return () -> {
if (!isPageInTransition()) {
AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 871643e..9001a0c 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -119,7 +119,7 @@
final Runnable onCompleteRunnable) {
return reverse
? new FolderPreviewItemAnim(this, mFirstPageParams.get(0), 0, 2, -1, -1,
- FINAL_ITEM_ANIMATION_DURATION, onCompleteRunnable)
+ FINAL_ITEM_ANIMATION_DURATION, onCompleteRunnable)
: new FolderPreviewItemAnim(this, mFirstPageParams.get(0), -1, -1, 0, 2,
INITIAL_ITEM_ANIMATION_DURATION, onCompleteRunnable);
}
@@ -219,9 +219,9 @@
/**
* Draws each preview item.
*
- * @param offset The offset needed to draw the preview items.
+ * @param offset The offset needed to draw the preview items.
* @param shouldClipPath Iff true, clip path using {@param clipPath}.
- * @param clipPath The clip path of the folder icon.
+ * @param clipPath The clip path of the folder icon.
*/
private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params, PointF offset,
boolean shouldClipPath, Path clipPath) {
@@ -362,13 +362,13 @@
/**
* Handles the case where items in the preview are either:
- * - Moving into the preview
- * - Moving into a new position
- * - Moving out of the preview
+ * - Moving into the preview
+ * - Moving into a new position
+ * - Moving out of the preview
*
* @param oldItems The list of items in the old preview.
* @param newItems The list of items in the new preview.
- * @param dropped The item that was dropped onto the FolderIcon.
+ * @param dropped The item that was dropped onto the FolderIcon.
*/
public void onDrop(List<WorkspaceItemInfo> oldItems, List<WorkspaceItemInfo> newItems,
WorkspaceItemInfo dropped) {
@@ -433,9 +433,8 @@
@VisibleForTesting
public void setDrawable(PreviewItemDrawingParams p, WorkspaceItemInfo item) {
if (item.hasPromiseIconUi() || (item.runtimeStatusFlags
- & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
+ & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
PreloadIconDrawable drawable = newPendingIcon(mContext, item);
- drawable.setLevel(item.getProgressLevel());
p.drawable = drawable;
} else {
p.drawable = item.newIcon(mContext,
@@ -443,7 +442,6 @@
}
p.drawable.setBounds(0, 0, mIconSize, mIconSize);
p.item = item;
-
// Set the callback to FolderIcon as it is responsible to drawing the icon. The
// callback will be released when the folder is opened.
p.drawable.setCallback(mIcon);
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 3e77c78..9fffcc1 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -173,6 +173,8 @@
mIconScaleMultiplier.updateValue(info.getProgressLevel() == 0 ? 0 : 1);
setLevel(info.getProgressLevel());
+ // Set a disabled icon color if the app is suspended or if the app is pending download
+ setIsDisabled(info.isDisabled() || info.isPendingDownload());
}
@Override
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index e46c502..352c363 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -139,7 +139,8 @@
*/
private int mProgressLevel = 100;
- protected ItemInfoWithIcon() { }
+ protected ItemInfoWithIcon() {
+ }
protected ItemInfoWithIcon(ItemInfoWithIcon info) {
super(info);
@@ -155,7 +156,20 @@
}
/**
- * Returns true if the app corresponding to the item is archived. */
+ * @return {@code true} if the app is pending download (0 progress) or if the app is archived
+ * and its install session is active
+ */
+ public boolean isPendingDownload() {
+ if (isArchived()) {
+ return this.getProgressLevel() == 0
+ && (this.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0;
+ }
+ return getProgressLevel() == 0;
+ }
+
+ /**
+ * Returns true if the app corresponding to the item is archived.
+ */
public boolean isArchived() {
if (!Utilities.enableSupportForArchiving()) {
return false;
@@ -179,7 +193,7 @@
public boolean isAppStartable() {
return ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) == 0)
&& (((runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0)
- || mProgressLevel == 100 || isArchived());
+ || mProgressLevel == 100 || isArchived());
}
/**
@@ -242,7 +256,7 @@
return targetPackage != null
? ApiWrapper.getAppMarketActivityIntent(
- context, targetPackage, Process.myUserHandle())
+ context, targetPackage, Process.myUserHandle())
: null;
}
diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
index 20ba04b..a5d5884 100644
--- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
@@ -121,6 +121,7 @@
@Test
@PortraitLandscape
@PlatinumTest(focusArea = "launcher")
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/326130648
public void testUninstallFromAllApps() throws Exception {
installDummyAppAndWaitForUIUpdate();
try {
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index 5283c6b..8631f03 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -11,11 +11,11 @@
import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static com.android.launcher3.util.TestUtil.DUMMY_CLASS_NAME;
import static com.android.launcher3.util.TestUtil.DUMMY_PACKAGE;
import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static com.google.common.truth.Truth.assertThat;
@@ -40,13 +40,14 @@
import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.TestStabilityRule;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.io.IOException;
@@ -61,6 +62,9 @@
@RunWith(AndroidJUnit4.class)
public class CacheDataUpdatedTaskTest {
+ @Rule(order = 0)
+ public TestRule testStabilityRule = new TestStabilityRule();
+
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -157,6 +161,7 @@
}
@Test
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/325283522
public void testSessionUpdate_updates_pending_apps() {
// Run on model executor so that no other task runs in the middle.
runOnExecutorSync(MODEL_EXECUTOR, () -> {
diff --git a/tests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt b/tests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt
new file mode 100644
index 0000000..cfbde98
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt
@@ -0,0 +1,68 @@
+/*
+ * 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
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.pm.PackageInstallInfo
+import com.android.launcher3.util.LauncherModelHelper
+import com.google.common.truth.Truth
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ItemInfoWithIconTest {
+
+ private var context = LauncherModelHelper.SandboxModelContext()
+ private lateinit var itemInfoWithIcon: ItemInfoWithIcon
+
+ @Before
+ fun setup() {
+ itemInfoWithIcon =
+ object : ItemInfoWithIcon() {
+ override fun clone(): ItemInfoWithIcon? {
+ return null
+ }
+ }
+ }
+
+ @After
+ fun tearDown() {
+ context.destroy()
+ }
+
+ @Test
+ fun itemInfoWithIconDefaultParamsTest() {
+ Truth.assertThat(itemInfoWithIcon.isDisabled).isFalse()
+ Truth.assertThat(itemInfoWithIcon.isPendingDownload).isFalse()
+ Truth.assertThat(itemInfoWithIcon.isArchived).isFalse()
+ }
+
+ @Test
+ fun isDisabledOrPendingTest() {
+ itemInfoWithIcon.setProgressLevel(0, PackageInstallInfo.STATUS_INSTALLING)
+ Truth.assertThat(itemInfoWithIcon.isDisabled).isFalse()
+ Truth.assertThat(itemInfoWithIcon.isPendingDownload).isTrue()
+
+ itemInfoWithIcon.setProgressLevel(1, PackageInstallInfo.STATUS_INSTALLING)
+ Truth.assertThat(itemInfoWithIcon.isDisabled).isFalse()
+ Truth.assertThat(itemInfoWithIcon.isPendingDownload).isFalse()
+ }
+}