Merge "Revert "When scrolling in All apps, scroll to last clickable row"" into ub-launcher3-master
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 8db875b..555cc73 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -169,7 +169,7 @@
<activity
android:name="com.android.launcher3.settings.SettingsActivity"
android:label="@string/settings_button_text"
- android:theme="@android:style/Theme.DeviceDefault.Settings"
+ android:theme="@style/HomeSettingsTheme"
android:autoRemoveFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
diff --git a/go/quickstep/res/values/override.xml b/go/quickstep/res/values/override.xml
index 7636fb3..bb267a3 100644
--- a/go/quickstep/res/values/override.xml
+++ b/go/quickstep/res/values/override.xml
@@ -22,5 +22,7 @@
<string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
<string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+
+ <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
</resources>
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index 535c5d8..8bd9dba 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -44,6 +44,7 @@
private final PackageManager mPm;
private final ColorExtractor mColorExtractor;
private boolean mDisableColorExtractor;
+ private boolean mBadgeOnLeft = false;
protected final int mFillResIconDpi;
protected final int mIconBitmapSize;
@@ -77,6 +78,7 @@
protected void clear() {
mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND;
mDisableColorExtractor = false;
+ mBadgeOnLeft = false;
}
public ShadowGenerator getShadowGenerator() {
@@ -201,6 +203,13 @@
}
/**
+ * Switches badging to left/right
+ */
+ public void setBadgeOnLeft(boolean badgeOnLeft) {
+ mBadgeOnLeft = badgeOnLeft;
+ }
+
+ /**
* Sets the background color used for wrapped adaptive icon
*/
public void setWrapperBackgroundColor(int color) {
@@ -261,8 +270,12 @@
*/
public void badgeWithDrawable(Canvas target, Drawable badge) {
int badgeSize = getBadgeSizeForIconSize(mIconBitmapSize);
- badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize,
- mIconBitmapSize, mIconBitmapSize);
+ if (mBadgeOnLeft) {
+ badge.setBounds(0, mIconBitmapSize - badgeSize, badgeSize, mIconBitmapSize);
+ } else {
+ badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize,
+ mIconBitmapSize, mIconBitmapSize);
+ }
badge.draw(target);
}
diff --git a/quickstep/recents_ui_overrides/res/values/override.xml b/quickstep/recents_ui_overrides/res/values/override.xml
index 1ddd3f5..ed3ba92 100644
--- a/quickstep/recents_ui_overrides/res/values/override.xml
+++ b/quickstep/recents_ui_overrides/res/values/override.xml
@@ -24,5 +24,7 @@
<string name="app_launch_tracker_class" translatable="false">com.android.launcher3.appprediction.PredictionAppTracker</string>
<string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+
+ <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherAppPredictionExtension</string>
</resources>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 8338c2e..f9ee701 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -24,11 +24,15 @@
import android.content.ComponentName;
import android.content.Context;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
+import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.Utilities;
@@ -36,12 +40,14 @@
import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.MainThreadInitializedObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.IntStream;
/**
* Handler responsible to updating the UI due to predicted apps changes. Operations:
@@ -294,6 +300,30 @@
return mCurrentState;
}
+ /**
+ * Fill in predicted_rank field based on app prediction.
+ * Only applicable when {@link ItemInfo#itemType} is one of the followings:
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
+ */
+ public static void fillInPredictedRank(
+ @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
+ final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
+ if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
+ || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+ && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
+ return;
+ }
+ final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+ final List<ComponentKeyMapper> predictedApps = manager.getCurrentState().apps;
+ IntStream.range(0, predictedApps.size())
+ .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+ .findFirst()
+ .ifPresent((rank) -> target.predictedRank = rank);
+ }
+
public static class PredictionState {
public boolean isEnabled;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index f3cbc08..bb66ae1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -69,7 +69,7 @@
return super.getOverviewScaleAndTranslation(launcher);
}
TaskView dummyTask;
- if (recentsView.getCurrentPage() >= 0) {
+ if (recentsView.getCurrentPage() >= recentsView.getTaskViewStartIndex()) {
if (recentsView.getCurrentPage() <= taskCount - 1) {
dummyTask = recentsView.getCurrentPageTaskView();
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
index c5cded0..3d664be 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
@@ -75,6 +75,7 @@
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider;
import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.SharedApiCompat;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.views.LiveTileOverlay;
@@ -176,8 +177,6 @@
private boolean mHasLauncherTransitionControllerStarted;
private AnimationFactory mAnimationFactory = (t) -> { };
- private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
- private boolean mLiveTileOverlayAttached = false;
private boolean mWasLauncherAlreadyVisible;
@@ -547,7 +546,8 @@
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationTargets != null) {
- mLiveTileOverlay.update(mAppWindowAnimationHelper.getCurrentRectWithInsets(),
+ LiveTileOverlay.getInstance().update(
+ mAppWindowAnimationHelper.getCurrentRectWithInsets(),
mAppWindowAnimationHelper.getCurrentCornerRadius());
}
}
@@ -837,7 +837,7 @@
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
} else if (endTarget == RECENTS) {
- mLiveTileOverlay.startIconAnimation();
+ LiveTileOverlay.getInstance().startIconAnimation();
if (mRecentsView != null) {
int nearestPage = mRecentsView.getPageNearestToCenterOfScreen();
if (mRecentsView.getNextPage() != nearestPage) {
@@ -1024,6 +1024,7 @@
// In the off chance that the gesture ends before Launcher is started, we should clear
// the callback here so that it doesn't update with the wrong state
mActivity.clearRunOnceOnStartCallback();
+ resetLauncherListenersAndOverlays();
}
if (mGestureState.getEndTarget() != null && !mGestureState.isRunningAnimationToLauncher()) {
cancelCurrentAnimation();
@@ -1111,13 +1112,7 @@
endLauncherTransitionController();
mRecentsView.onGestureAnimationEnd();
-
- // Reset the callback for deferred activity launches
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mActivityInterface.setOnDeferredActivityLaunchCallback(null);
- }
- mActivity.getRootView().setOnApplyWindowInsetsListener(null);
- removeLiveTileOverlay();
+ resetLauncherListenersAndOverlays();
}
private void endLauncherTransitionController() {
@@ -1128,6 +1123,15 @@
}
}
+ private void resetLauncherListenersAndOverlays() {
+ // Reset the callback for deferred activity launches
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ mActivityInterface.setOnDeferredActivityLaunchCallback(null);
+ }
+ mActivity.getRootView().setOnApplyWindowInsetsListener(null);
+ removeLiveTileOverlay();
+ }
+
private void notifyTransitionCancelled() {
mAnimationFactory.onTransitionCancelled();
}
@@ -1144,6 +1148,8 @@
final int runningTaskId = mGestureState.getRunningTaskId();
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationController != null) {
+ SharedApiCompat.setWillFinishToHome(mRecentsAnimationController.getController(),
+ true /* willFinishToHome */);
// Update the screenshot of the task
if (mTaskSnapshot == null) {
mTaskSnapshot = mRecentsAnimationController.screenshotTask(runningTaskId);
@@ -1232,20 +1238,15 @@
updateFinalShift();
}
- private synchronized void addLiveTileOverlay() {
- if (!mLiveTileOverlayAttached) {
- mActivity.getRootView().getOverlay().add(mLiveTileOverlay);
- mRecentsView.setLiveTileOverlay(mLiveTileOverlay);
- mLiveTileOverlayAttached = true;
+ private void addLiveTileOverlay() {
+ if (LiveTileOverlay.getInstance().attach(mActivity.getRootView().getOverlay())) {
+ mRecentsView.setLiveTileOverlayAttached(true);
}
}
- private synchronized void removeLiveTileOverlay() {
- if (mLiveTileOverlayAttached) {
- mActivity.getRootView().getOverlay().remove(mLiveTileOverlay);
- mRecentsView.setLiveTileOverlay(null);
- mLiveTileOverlayAttached = false;
- }
+ private void removeLiveTileOverlay() {
+ LiveTileOverlay.getInstance().detach(mActivity.getRootView().getOverlay());
+ mRecentsView.setLiveTileOverlayAttached(false);
}
public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, float expectedAlpha) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
new file mode 100644
index 0000000..b251f9e
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/logging/UserEventDispatcherAppPredictionExtension.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 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.logging;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.appprediction.PredictionUiStateManager;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+
+/**
+ * This class handles AOSP MetricsLogger function calls and logging around
+ * quickstep interactions and app launches.
+ */
+@SuppressWarnings("unused")
+public class UserEventDispatcherAppPredictionExtension extends UserEventDispatcherExtension {
+
+ public static final int ALL_APPS_PREDICTION_TIPS = 2;
+
+ private static final String TAG = "UserEventDispatcher";
+
+ public UserEventDispatcherAppPredictionExtension(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onFillInLogContainerData(
+ @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target,
+ @NonNull LauncherLogProto.Target targetParent) {
+ PredictionUiStateManager.fillInPredictedRank(itemInfo, target);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index ca33605..82fbbc6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -326,8 +326,8 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- PluginManagerWrapper.INSTANCE.get(getContext())
- .addPluginListener(mRecentsExtraCardPluginListener, RecentsExtraCard.class);
+ PluginManagerWrapper.INSTANCE.get(getContext()).addPluginListener(
+ mRecentsExtraCardPluginListener, RecentsExtraCard.class);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
index a838797..18eda60 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
@@ -16,6 +16,7 @@
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
+import android.view.ViewOverlay;
import com.android.launcher3.anim.Interpolators;
@@ -36,6 +37,15 @@
}
};
+ private static LiveTileOverlay sInstance;
+
+ public static LiveTileOverlay getInstance() {
+ if (sInstance == null) {
+ sInstance = new LiveTileOverlay();
+ }
+ return sInstance;
+ }
+
private final Paint mPaint = new Paint();
private Rect mBoundsRect = new Rect();
@@ -46,8 +56,9 @@
private boolean mDrawEnabled = true;
private float mIconAnimationProgress = 0f;
+ private boolean mIsAttached;
- public LiveTileOverlay() {
+ private LiveTileOverlay() {
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
@@ -124,6 +135,23 @@
return PixelFormat.TRANSLUCENT;
}
+ public boolean attach(ViewOverlay overlay) {
+ if (overlay != null && !mIsAttached) {
+ overlay.add(this);
+ mIsAttached = true;
+ return true;
+ }
+
+ return false;
+ }
+
+ public void detach(ViewOverlay overlay) {
+ if (overlay != null) {
+ overlay.remove(this);
+ mIsAttached = false;
+ }
+ }
+
private void setIconAnimationProgress(float progress) {
mIconAnimationProgress = progress;
invalidateSelf();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index cf616fe..56c2dd5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -308,7 +308,7 @@
private final int mEmptyMessagePadding;
private boolean mShowEmptyMessage;
private Layout mEmptyTextLayout;
- private LiveTileOverlay mLiveTileOverlay;
+ private boolean mLiveTileOverlayAttached;
// Keeps track of the index where the first TaskView should be
private int mTaskViewStartIndex = 0;
@@ -876,8 +876,8 @@
*/
public void onSwipeUpAnimationSuccess() {
if (getRunningTaskView() != null) {
- float startProgress = ENABLE_QUICKSTEP_LIVE_TILE.get() && mLiveTileOverlay != null
- ? mLiveTileOverlay.cancelIconAnimation()
+ float startProgress = ENABLE_QUICKSTEP_LIVE_TILE.get() && mLiveTileOverlayAttached
+ ? LiveTileOverlay.getInstance().cancelIconAnimation()
: 0f;
animateUpRunningTaskIconScale(startProgress);
}
@@ -1724,13 +1724,13 @@
mAppWindowAnimationHelper = appWindowAnimationHelper;
}
- public void setLiveTileOverlay(LiveTileOverlay liveTileOverlay) {
- mLiveTileOverlay = liveTileOverlay;
+ public void setLiveTileOverlayAttached(boolean liveTileOverlayAttached) {
+ mLiveTileOverlayAttached = liveTileOverlayAttached;
}
public void updateLiveTileIcon(Drawable icon) {
- if (mLiveTileOverlay != null) {
- mLiveTileOverlay.setIcon(icon);
+ if (mLiveTileOverlayAttached) {
+ LiveTileOverlay.getInstance().setIcon(icon);
}
}
@@ -1855,8 +1855,8 @@
private void updateEnabledOverlays() {
int overlayEnabledPage = mOverlayEnabled ? getNextPage() : -1;
int taskCount = getTaskViewCount();
- for (int i = 0; i < taskCount; i++) {
- getTaskViewAt(i).setOverlayEnabled(i == overlayEnabledPage);
+ for (int i = mTaskViewStartIndex; i < mTaskViewStartIndex + taskCount; i++) {
+ getTaskViewAtByAbsoluteIndex(i).setOverlayEnabled(i == overlayEnabledPage);
}
}
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 5d9a009..327bb14 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -19,8 +19,6 @@
<!-- Activity which blocks home gesture -->
<string name="gesture_blocking_activity" translatable="false"></string>
- <string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
-
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
<string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 333e179..46af8bf 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -18,6 +18,7 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
+
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@@ -185,6 +186,11 @@
mInputConsumerController.setInputListener(this::onInputConsumerEvent);
}
+ /** @return wrapper controller. */
+ public RecentsAnimationControllerCompat getController() {
+ return mController;
+ }
+
private void disableInputProxy() {
if (mInputConsumer != null && mTouchInProgress) {
long now = SystemClock.uptimeMillis();
diff --git a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
index 4a11601..9ca7f23 100644
--- a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
+++ b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
@@ -20,10 +20,10 @@
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index ca81343..119288c 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -133,7 +133,7 @@
@NavigationModeSwitch
@Test
public void goToOverviewFromHome() {
- // b/142828227
+ // b/143488140
if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
(RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
@@ -148,7 +148,7 @@
@NavigationModeSwitch
@Test
public void goToOverviewFromApp() {
- // b/142828227
+ // b/143488140
if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
(RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
@@ -187,7 +187,7 @@
@NavigationModeSwitch
@Test
public void testOverview() {
- // b/142828227
+ // b/143488140
if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
(RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 339aef5..80c791c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -130,6 +130,10 @@
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
</style>
+ <style name="HomeSettingsTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ </style>
+
<!--
Theme overrides to element on homescreen, i.e., which are drawn on top on wallpaper.
Various foreground colors are overridden to be workspaceTextColor so that they are properly
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 431a149..d445bc9 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1278,6 +1278,10 @@
return !mLauncher.isInState(NORMAL);
}
+ private boolean workspaceInScrollableState() {
+ return mLauncher.isInState(SPRING_LOADED) || !workspaceInModalState();
+ }
+
/** Returns whether a drag should be allowed to be started from the current workspace state. */
public boolean workspaceIconsCanBeDragged() {
return mLauncher.getStateManager().getState().workspaceIconsCanBeDragged;
@@ -2879,7 +2883,7 @@
@Override
public boolean scrollLeft() {
boolean result = false;
- if (!workspaceInModalState() && !mIsSwitchingState) {
+ if (!mIsSwitchingState && workspaceInScrollableState()) {
result = super.scrollLeft();
}
Folder openFolder = Folder.getOpen(mLauncher);
@@ -2892,7 +2896,7 @@
@Override
public boolean scrollRight() {
boolean result = false;
- if (!workspaceInModalState() && !mIsSwitchingState) {
+ if (!mIsSwitchingState && workspaceInScrollableState()) {
result = super.scrollRight();
}
Folder openFolder = Folder.getOpen(mLauncher);
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 22dda41..a7fa379 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -74,7 +74,10 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.logging.LoggerUtils;
import com.android.launcher3.pageindicators.PageIndicatorDots;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ClipPathView;
@@ -559,7 +562,11 @@
mState = STATE_OPEN;
announceAccessibilityChanges();
- mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("folder opened");
+ mLauncher.getUserEventDispatcher().logActionOnItem(
+ Touch.TAP,
+ Direction.NONE,
+ ItemType.FOLDER_ICON, mInfo.cellX, mInfo.cellY);
+
mContent.setFocusOnFirstChild();
}
});
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 9b75b43..598792a 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -44,6 +44,7 @@
public class LoggerUtils {
private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
private static final String UNKNOWN = "UNKNOWN";
+ private static final int DEFAULT_PREDICTED_RANK = -100;
public static String getFieldName(int value, Class c) {
SparseArray<String> cache;
@@ -90,7 +91,7 @@
}
public static String getTargetStr(Target t) {
- if (t == null){
+ if (t == null) {
return "";
}
String str = "";
@@ -137,17 +138,16 @@
if (t.intentHash != 0) {
typeStr += ", intentHash=" + t.intentHash;
}
- if ((t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) &&
- t.itemType != ItemType.TASK) {
+ if (t.itemType == ItemType.FOLDER_ICON) {
+ typeStr += ", grid(" + t.gridX + "," + t.gridY + ")";
+ } else if ((t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0)
+ && t.itemType != ItemType.TASK) {
typeStr += ", predictiveRank=" + t.predictedRank + ", grid(" + t.gridX + "," + t.gridY
- + "), span(" + t.spanX + "," + t.spanY
- + "), pageIdx=" + t.pageIndex;
-
+ + "), span(" + t.spanX + "," + t.spanY + "), pageIdx=" + t.pageIndex;
}
if (t.searchQueryLength != 0) {
typeStr += ", searchQueryLength=" + t.searchQueryLength;
}
-
if (t.itemType == ItemType.TASK) {
typeStr += ", pageIdx=" + t.pageIndex;
}
@@ -168,17 +168,17 @@
public static Target newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver) {
Target t = newTarget(Target.Type.ITEM);
-
switch (info.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
t.itemType = (instantAppResolver != null && info instanceof AppInfo
- && instantAppResolver.isInstantApp(((AppInfo) info)) )
+ && instantAppResolver.isInstantApp(((AppInfo) info)))
? ItemType.WEB_APP
: ItemType.APP_ICON;
- t.predictedRank = -100; // Never assigned
+ t.predictedRank = DEFAULT_PREDICTED_RANK;
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
t.itemType = ItemType.SHORTCUT;
+ t.predictedRank = DEFAULT_PREDICTED_RANK;
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
t.itemType = ItemType.FOLDER_ICON;
@@ -188,6 +188,7 @@
break;
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
t.itemType = ItemType.DEEPSHORTCUT;
+ t.predictedRank = DEFAULT_PREDICTED_RANK;
break;
}
return t;
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 21ca74e..99906fe 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -26,6 +26,8 @@
import static com.android.launcher3.logging.LoggerUtils.newTarget;
import static com.android.launcher3.logging.LoggerUtils.newTouchAction;
+import static java.util.Optional.ofNullable;
+
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -35,6 +37,7 @@
import android.util.Log;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.DropTarget;
@@ -58,7 +61,7 @@
/**
* Manages the creation of {@link LauncherEvent}.
* To debug this class, execute following command before side loading a new apk.
- *
+ * <p>
* $ adb shell setprop log.tag.UserEvent VERBOSE
*/
public class UserEventDispatcher implements ResourceBasedOverride {
@@ -94,19 +97,26 @@
/**
* Fills in the container data on the given event if the given view is not null.
+ *
* @return whether container data was added.
*/
- public static boolean fillInLogContainerData(LauncherLogProto.LauncherEvent event, @Nullable View v) {
+ public boolean fillInLogContainerData(LauncherLogProto.LauncherEvent event, @Nullable View v) {
// Fill in grid(x,y), pageIndex of the child and container type of the parent
LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
return false;
}
- ItemInfo itemInfo = (ItemInfo) v.getTag();
- provider.fillInLogContainerData(v, itemInfo, event.srcTarget[0], event.srcTarget[1]);
+ final ItemInfo itemInfo = (ItemInfo) v.getTag();
+ final Target target = event.srcTarget[0];
+ final Target targetParent = event.srcTarget[1];
+ onFillInLogContainerData(itemInfo, target, targetParent);
+ provider.fillInLogContainerData(v, itemInfo, target, targetParent);
return true;
}
+ protected void onFillInLogContainerData(
+ @NonNull ItemInfo itemInfo, @NonNull Target target, @NonNull Target targetParent) { }
+
private boolean mSessionStarted;
private long mElapsedContainerMillis;
private long mElapsedSessionMillis;
@@ -139,7 +149,11 @@
mAppOrTaskLaunch = true;
}
- public void logActionTip(int actionType, int viewType) { }
+ /**
+ * Dummy method.
+ */
+ public void logActionTip(int actionType, int viewType) {
+ }
@Deprecated
public void logTaskLaunchOrDismiss(int action, int direction, int taskIndex,
@@ -184,15 +198,15 @@
public void logActionCommand(int command, int srcContainerType, int dstContainerType) {
logActionCommand(command, newContainerTarget(srcContainerType),
- dstContainerType >=0 ? newContainerTarget(dstContainerType) : null);
+ dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null);
}
public void logActionCommand(int command, int srcContainerType, int dstContainerType,
- int pageIndex) {
+ int pageIndex) {
Target srcTarget = newContainerTarget(srcContainerType);
srcTarget.pageIndex = pageIndex;
logActionCommand(command, srcTarget,
- dstContainerType >=0 ? newContainerTarget(dstContainerType) : null);
+ dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null);
}
public void logActionCommand(int command, Target srcTarget, Target dstTarget) {
@@ -241,7 +255,7 @@
}
public void logActionOnControl(int action, int controlType, int parentContainer,
- int grandParentContainer){
+ int grandParentContainer) {
LauncherEvent event = newLauncherEvent(newTouchAction(action),
newControlTarget(controlType),
newContainerTarget(parentContainer),
@@ -250,11 +264,11 @@
}
public void logActionOnControl(int action, int controlType, @Nullable View controlInContainer,
- int parentContainerType) {
+ int parentContainerType) {
final LauncherEvent event = (controlInContainer == null && parentContainerType < 0)
? newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL))
: newLauncherEvent(newTouchAction(action), newTarget(Target.Type.CONTROL),
- newTarget(Target.Type.CONTAINER));
+ newTarget(Target.Type.CONTAINER));
event.srcTarget[0].controlType = controlType;
if (controlInContainer != null) {
fillInLogContainerData(event, controlInContainer);
@@ -301,9 +315,9 @@
* (1) WORKSPACE: if the launcher is the foreground activity
* (2) APP: if another app was the foreground activity
*/
- public void logStateChangeAction(int action, int dir, int downX, int downY, int srcChildTargetType,
- int srcParentContainerType, int dstContainerType,
- int pageIndex) {
+ public void logStateChangeAction(int action, int dir, int downX, int downY,
+ int srcChildTargetType, int srcParentContainerType, int dstContainerType,
+ int pageIndex) {
LauncherEvent event;
if (srcChildTargetType == LauncherLogProto.ItemType.TASK) {
event = newLauncherEvent(newTouchAction(action),
@@ -326,9 +340,25 @@
}
public void logActionOnItem(int action, int dir, int itemType) {
+ logActionOnItem(action, dir, itemType, null, null);
+ }
+
+ /**
+ * Creates new {@link LauncherEvent} of ITEM target type with input arguments and dispatches it.
+ *
+ * @param touchAction ENUM value of {@link LauncherLogProto.Action.Touch} Action
+ * @param dir ENUM value of {@link LauncherLogProto.Action.Direction} Action
+ * @param itemType ENUM value of {@link LauncherLogProto.ItemType}
+ * @param gridX Nullable X coordinate of item's position on the workspace grid
+ * @param gridY Nullable Y coordinate of item's position on the workspace grid
+ */
+ public void logActionOnItem(int touchAction, int dir, int itemType,
+ @Nullable Integer gridX, @Nullable Integer gridY) {
Target itemTarget = newTarget(Target.Type.ITEM);
itemTarget.itemType = itemType;
- LauncherEvent event = newLauncherEvent(newTouchAction(action), itemTarget);
+ ofNullable(gridX).ifPresent(value -> itemTarget.gridX = value);
+ ofNullable(gridY).ifPresent(value -> itemTarget.gridY = value);
+ LauncherEvent event = newLauncherEvent(newTouchAction(touchAction), itemTarget);
event.action.dir = dir;
dispatchUserEvent(event, null);
}
@@ -351,7 +381,7 @@
LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.DRAGDROP),
newItemTarget(dragObj.originalDragInfo, mInstantAppResolver),
newTarget(Target.Type.CONTAINER));
- event.destTarget = new Target[] {
+ event.destTarget = new Target[]{
newItemTarget(dragObj.originalDragInfo, mInstantAppResolver),
newDropTarget(dropTargetAsView)
};
@@ -373,14 +403,10 @@
int actionTouch = isButton ? Action.Touch.TAP : Action.Touch.SWIPE;
Action action = newCommandAction(actionTouch);
action.command = Action.Command.BACK;
- action.dir = isButton
- ? Action.Direction.NONE
- : gestureSwipeLeft
- ? Action.Direction.LEFT
- : Action.Direction.RIGHT;
- Target target = newControlTarget(isButton
- ? LauncherLogProto.ControlType.BACK_BUTTON
- : LauncherLogProto.ControlType.BACK_GESTURE);
+ action.dir = isButton ? Action.Direction.NONE :
+ gestureSwipeLeft ? Action.Direction.LEFT : Action.Direction.RIGHT;
+ Target target = newControlTarget(isButton ? LauncherLogProto.ControlType.BACK_BUTTON :
+ LauncherLogProto.ControlType.BACK_GESTURE);
target.spanX = downX;
target.spanY = downY;
target.cardinality = completed ? 1 : 0;
@@ -391,6 +417,7 @@
/**
* Currently logs following containers: workspace, allapps, widget tray.
+ *
* @param reason
*/
public final void resetElapsedContainerMillis(String reason) {
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 0e73829..059ad18 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -115,8 +115,8 @@
switch (message.what) {
case MSG_NOTIFICATION_POSTED: {
StatusBarNotification sbn = (StatusBarNotification) message.obj;
- mUiHandler.obtainMessage(shouldBeFilteredOut(sbn)
- ? MSG_NOTIFICATION_REMOVED : MSG_NOTIFICATION_POSTED,
+ mUiHandler.obtainMessage(notificationIsValidForUI(sbn)
+ ? MSG_NOTIFICATION_POSTED : MSG_NOTIFICATION_REMOVED,
toKeyPair(sbn)).sendToTarget();
return true;
}
@@ -148,7 +148,7 @@
if (sIsConnected) {
try {
activeNotifications = Arrays.stream(getActiveNotifications())
- .filter(this::shouldBeFilteredOut)
+ .filter(this::notificationIsValidForUI)
.collect(Collectors.toList());
} catch (SecurityException ex) {
Log.e(TAG, "SecurityException: failed to fetch notifications");
@@ -305,22 +305,22 @@
}
/**
- * Returns true for notifications that don't have an intent
- * or are headers for grouped notifications and should be filtered out.
+ * Returns true for notifications that have an intent and are not headers for grouped
+ * notifications and should be shown in the notification popup.
*/
@WorkerThread
- private boolean shouldBeFilteredOut(StatusBarNotification sbn) {
+ private boolean notificationIsValidForUI(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
updateGroupKeyIfNecessary(sbn);
getCurrentRanking().getRanking(sbn.getKey(), mTempRanking);
if (!mTempRanking.canShowBadge()) {
- return true;
+ return false;
}
if (mTempRanking.getChannel().getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
// Special filtering for the default, legacy "Miscellaneous" channel.
if ((notification.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
- return true;
+ return false;
}
}
@@ -328,7 +328,7 @@
CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
boolean missingTitleAndText = TextUtils.isEmpty(title) && TextUtils.isEmpty(text);
boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
- return (isGroupHeader || missingTitleAndText);
+ return !isGroupHeader && !missingTitleAndText;
}
private static Pair<PackageUserKey, NotificationKeyData> toKeyPair(StatusBarNotification sbn) {
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 64df384..40e267b 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -173,6 +173,12 @@
mLeaks.add(new View(mContext));
break;
}
+
+ case TestProtocol.REQUEST_ICON_HEIGHT: {
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ mDeviceProfile.allAppsCellHeightPx);
+ break;
+ }
}
return response;
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 1cfa4af..832f7f0 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -63,6 +63,8 @@
"all-apps-to-overview-swipe-height";
public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT =
"home-to-all-apps-swipe-height";
+ public static final String REQUEST_ICON_HEIGHT =
+ "icon-height";
public static final String REQUEST_HOTSEAT_TOP = "hotseat-top";
public static final String REQUEST_IS_LAUNCHER_INITIALIZED = "is-launcher-initialized";
public static final String REQUEST_FREEZE_APP_LIST = "freeze-app-list";
diff --git a/src/com/android/launcher3/util/ViewPool.java b/src/com/android/launcher3/util/ViewPool.java
index 8af048d..5b33f18 100644
--- a/src/com/android/launcher3/util/ViewPool.java
+++ b/src/com/android/launcher3/util/ViewPool.java
@@ -21,12 +21,12 @@
import android.view.View;
import android.view.ViewGroup;
-import com.android.launcher3.util.ViewPool.Reusable;
-
import androidx.annotation.AnyThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import com.android.launcher3.util.ViewPool.Reusable;
+
/**
* Utility class to maintain a pool of reusable views.
* During initialization, views are inflated on the background thread.
@@ -58,14 +58,18 @@
Preconditions.assertUIThread();
Handler handler = new Handler();
+ // LayoutInflater is not thread save as it maintains a global variable 'mConstructorArgs'.
+ // Create a different copy to use on the background thread.
+ LayoutInflater inflater = mInflater.cloneInContext(mInflater.getContext());
+
// Inflate views on a non looper thread. This allows us to catch errors like calling
// "new Handler()" in constructor easily.
new Thread(() -> {
for (int i = 0; i < initialSize; i++) {
- T view = inflateNewView();
+ T view = inflateNewView(inflater);
handler.post(() -> addToPool(view));
}
- }).start();
+ }, "ViewPool-init").start();
}
@UiThread
@@ -94,12 +98,12 @@
mCurrentSize--;
return (T) mPool[mCurrentSize];
}
- return inflateNewView();
+ return inflateNewView(mInflater);
}
@AnyThread
- private T inflateNewView() {
- return (T) mInflater.inflate(mLayoutId, mParent, false);
+ private T inflateNewView(LayoutInflater inflater) {
+ return (T) inflater.inflate(mLayoutId, mParent, false);
}
/**
diff --git a/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java b/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java
index 0ebea3d..cd9f33d 100644
--- a/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java
+++ b/src_plugins/com/android/systemui/plugins/RecentsExtraCard.java
@@ -34,9 +34,9 @@
/**
* Sets up the recents overview extra card and fills in data.
*
- * @param context Plugin context
+ * @param context Plugin context
* @param frameLayout PlaceholderView
- * @param activity Recents activity to hold extra view
+ * @param activity Recents activity to hold extra view
*/
void setupView(Context context, FrameLayout frameLayout, Activity activity);
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 5a100c8..d7096b0 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -18,10 +18,6 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
-import static com.android.launcher3.util.rule.TestStabilityRule.RUN_FLAFOR;
-import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_PRESUBMIT;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -38,7 +34,6 @@
import com.android.launcher3.tapl.AppIcon;
import com.android.launcher3.tapl.AppIconMenu;
import com.android.launcher3.tapl.AppIconMenuItem;
-import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.views.OptionsPopupView;
@@ -344,23 +339,6 @@
}
}
- /**
- * Test dragging a custom shortcut to the workspace and launch it.
- *
- * A custom shortcut is a 1x1 widget that launches a specific intent when user tap on it.
- * Custom shortcuts are replaced by deep shortcuts after api 25.
- */
- @Test
- @PortraitLandscape
- public void testDragCustomShortcut() {
- if (!TestHelpers.isInLauncherProcess()) return; // b/143725213
- mLauncher.getWorkspace().openAllWidgets()
- .getWidget("com.android.launcher3.testcomponent.CustomShortcutConfigActivity")
- .dragToWorkspace();
- mLauncher.getWorkspace().getWorkspaceAppIcon("Shortcut")
- .launch(getAppPackageName());
- }
-
public static String getAppPackageName() {
return getInstrumentation().getContext().getPackageName();
}
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 259f9ed..f9d1d93 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -16,7 +16,6 @@
package com.android.launcher3.ui.widget;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
-import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_POSTSUBMIT;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -30,7 +29,6 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ShellCommandRule;
-import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import org.junit.Rule;
import org.junit.Test;
@@ -71,4 +69,22 @@
assertNotNull("Widget not found on the workspace", widget);
widget.launch(getAppPackageName());
}
+
+ /**
+ * Test dragging a custom shortcut to the workspace and launch it.
+ *
+ * A custom shortcut is a 1x1 widget that launches a specific intent when user tap on it.
+ * Custom shortcuts are replaced by deep shortcuts after api 25.
+ */
+ @Test
+ @PortraitLandscape
+ public void testDragCustomShortcut() throws Throwable {
+ clearHomescreen();
+ mDevice.pressHome();
+ mLauncher.getWorkspace().openAllWidgets()
+ .getWidget("com.android.launcher3.testcomponent.CustomShortcutConfigActivity")
+ .dragToWorkspace();
+ mLauncher.getWorkspace().getWorkspaceAppIcon("Shortcut")
+ .launch(getAppPackageName());
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index cc92327..481ca6c 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -36,6 +36,7 @@
private static final int MAX_SCROLL_ATTEMPTS = 40;
private final int mHeight;
+ private final int mIconHeight;
AllApps(LauncherInstrumentation launcher) {
super(launcher);
@@ -46,6 +47,9 @@
// Wait for the recycler to populate.
mLauncher.waitForObjectInContainer(appListRecycler, By.clazz(TextView.class));
verifyNotFrozen("All apps freeze flags upon opening all apps");
+ mIconHeight = mLauncher.getTestInfo(
+ TestProtocol.REQUEST_ICON_HEIGHT).
+ getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
@Override
@@ -62,6 +66,10 @@
}
final Rect iconBounds = icon.getVisibleBounds();
LauncherInstrumentation.log("hasClickableIcon: icon bounds: " + iconBounds);
+ if (iconBounds.height() < mIconHeight / 2) {
+ LauncherInstrumentation.log("hasClickableIcon: icon has insufficient height");
+ return false;
+ }
if (iconCenterInSearchBox(allAppsContainer, icon)) {
LauncherInstrumentation.log("hasClickableIcon: icon center is under search box");
return false;
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 1c851f4..37e99ed 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -696,8 +696,8 @@
final UiObject2 object = container.wait(
Until.findObject(getLauncherObjectSelector(resName)),
WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object id: " + resName + " in container: " +
- container.getResourceName(), object);
+ assertNotNull("Can't find a view in Launcher, id: " + resName + " in container: "
+ + container.getResourceName(), object);
return object;
}
@@ -706,8 +706,8 @@
final UiObject2 object = container.wait(
Until.findObject(selector),
WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object id: " + selector + " in container: " +
- container.getResourceName(), object);
+ assertNotNull("Can't find a view in Launcher, id: " + selector + " in container: "
+ + container.getResourceName(), object);
return object;
}
@@ -738,7 +738,7 @@
private UiObject2 waitForObjectBySelector(BySelector selector) {
final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object; selector: " + selector, object);
+ assertNotNull("Can't find a view in Launcher, selector: " + selector, object);
return object;
}