Merge "Refactoring One-Handed feature flag and others" into ub-launcher3-master
diff --git a/Android.mk b/Android.mk
index 7805b32..91ecccb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -48,7 +48,7 @@
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java
LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
+LOCAL_MIN_SDK_VERSION := 26
LOCAL_MODULE := Launcher3CommonDepsLib
LOCAL_PRIVILEGED_MODULE := true
LOCAL_MANIFEST_FILE := AndroidManifest-common.xml
@@ -77,7 +77,7 @@
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
+LOCAL_MIN_SDK_VERSION := 26
LOCAL_PACKAGE_NAME := Launcher3
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SYSTEM_EXT_MODULE := true
@@ -108,7 +108,7 @@
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
+LOCAL_MIN_SDK_VERSION := 26
LOCAL_PACKAGE_NAME := Launcher3Go
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SYSTEM_EXT_MODULE := true
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 19a16e3..97e3786 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -29,12 +29,6 @@
at compile time. Note that the components defined in AndroidManifest.xml are also required,
with some minor changed based on the derivative app.
-->
- <permission
- android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
- android:label="@string/permlab_install_shortcut"
- android:description="@string/permdesc_install_shortcut" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
@@ -79,17 +73,6 @@
android:restoreAnyVersion="true"
android:supportsRtl="true" >
- <!-- Intent received used to install shortcuts from other applications -->
- <receiver
- android:name="com.android.launcher3.InstallShortcutReceiver"
- android:permission="com.android.launcher.permission.INSTALL_SHORTCUT"
- android:exported="true"
- android:enabled="@bool/enable_install_shortcut_api" >
- <intent-filter>
- <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
- </intent-filter>
- </receiver>
-
<!-- Intent received when a session is committed -->
<receiver
android:name="com.android.launcher3.SessionCommitReceiver"
@@ -116,7 +99,6 @@
<service
android:name="com.android.launcher3.notification.NotificationListener"
android:label="@string/notification_dots_service_title"
- android:enabled="@bool/notification_dots_enabled"
android:exported="true"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4664c93..97bce9c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,7 +20,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
+ <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="26"/>
<!--
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
Refer comments around specific entries on how to extend individual components.
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java
index 914d9e9..7dc7bfc 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -42,6 +42,7 @@
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.Themes;
@@ -90,7 +91,8 @@
mLauncher = Launcher.getLauncher(context);
boolean isMainColorDark = Themes.getAttrBoolean(context, R.attr.isMainColorDark);
- mPaint.setStrokeWidth(getResources().getDimensionPixelSize(R.dimen.all_apps_divider_height));
+ mPaint.setStrokeWidth(
+ getResources().getDimensionPixelSize(R.dimen.all_apps_divider_height));
mStrokeColor = ContextCompat.getColor(context, isMainColorDark
? R.color.all_apps_prediction_row_separator_dark
@@ -134,7 +136,7 @@
if (row == this) {
break;
} else if (row.shouldDraw()) {
- sectionCount ++;
+ sectionCount++;
}
}
@@ -181,6 +183,11 @@
}
private void updateViewVisibility() {
+ // hide divider since we have item decoration for prediction row
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ setVisibility(GONE);
+ return;
+ }
setVisibility(mDividerType == DividerType.NONE
? GONE
: (mIsScrolledOut ? INVISIBLE : VISIBLE));
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
index 55384af..8a810e3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -45,10 +45,12 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsSectionDecorator;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusIndicatorHelper;
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
@@ -110,6 +112,8 @@
private boolean mPredictionsEnabled = false;
+ AllAppsSectionDecorator.SectionDecorationHandler mDecorationHandler;
+
public PredictionRowView(@NonNull Context context) {
this(context, null);
}
@@ -128,6 +132,11 @@
mIconFullTextAlpha = Color.alpha(mIconTextColor);
mIconCurrentTextAlpha = mIconFullTextAlpha;
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ mDecorationHandler = new AllAppsSectionDecorator.SectionDecorationHandler(getContext(),
+ false);
+ }
+
updateVisibility();
}
@@ -153,6 +162,14 @@
@Override
protected void dispatchDraw(Canvas canvas) {
+ if (mDecorationHandler != null) {
+ mDecorationHandler.reset();
+ int childrenCount = getChildCount();
+ for (int i = 0; i < childrenCount; i++) {
+ mDecorationHandler.extendBounds(getChildAt(i));
+ }
+ mDecorationHandler.onDraw(canvas);
+ }
mFocusHelper.draw(canvas);
super.dispatchDraw(canvas);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 37a595e..fce019b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.uioverrides.touchcontrollers;
import static com.android.launcher3.AbstractFloatingView.TYPE_ACCESSIBLE;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_BOTH;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSITIVE;
@@ -262,13 +261,6 @@
mCurrentAnimation.setPlayFraction(Utilities.boundToRange(
totalDisplacement * mProgressMultiplier, 0, 1));
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (mRecentsView.getCurrentPage() == 0) {
- mRecentsView.getLiveTileTaskViewSimulator().setOffsetY(
- isGoingUp ? totalDisplacement : 0);
- mRecentsView.redrawLiveTile();
- }
- }
return true;
}
@@ -299,13 +291,6 @@
}
mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction));
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mCurrentAnimation.getAnimationPlayer().addUpdateListener(valueAnimator -> {
- if (mRecentsView.getCurrentPage() != 0 || mCurrentAnimationIsGoingUp) {
- mRecentsView.redrawLiveTile();
- }
- });
- }
mCurrentAnimation.startWithVelocity(mActivity, goingToEnd,
velocity, mEndDisplacement, animationDuration);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
index f371145..b6d44eb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -23,7 +23,6 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@@ -48,7 +47,6 @@
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import android.animation.Animator;
-import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -75,7 +73,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
@@ -93,6 +90,7 @@
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.ShelfPeekAnim;
@@ -214,8 +212,7 @@
private ThumbnailData mTaskSnapshot;
// Used to control launcher components throughout the swipe gesture.
- private AnimatorPlaybackController mLauncherTransitionController;
- private boolean mHasLauncherTransitionControllerStarted;
+ private AnimatorControllerWithResistance mLauncherTransitionController;
private AnimationFactory mAnimationFactory = (t) -> { };
@@ -564,11 +561,11 @@
/**
* We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
- * (it has its own animation) or if we're already animating the current controller.
+ * (it has its own animation).
* @return Whether we can create the launcher controller or update its progress.
*/
private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
- return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
+ return mGestureState.getEndTarget() != HOME;
}
@Override
@@ -578,10 +575,9 @@
return result;
}
- private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
+ private void onAnimatorPlaybackControllerCreated(AnimatorControllerWithResistance anim) {
mLauncherTransitionController = anim;
- mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
- mLauncherTransitionController.dispatchOnStart();
+ mLauncherTransitionController.getNormalController().dispatchOnStart();
updateLauncherTransitionProgress();
}
@@ -621,10 +617,7 @@
|| !canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
}
- // Normalize the progress to 0 to 1, as the animation controller will clamp it to that
- // anyway. The controller mimics the drag length factor by applying it to its interpolators.
- float progress = mCurrentShift.value / mDragLengthFactor;
- mLauncherTransitionController.setPlayFraction(progress);
+ mLauncherTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor);
}
/**
@@ -1112,31 +1105,6 @@
windowAnim.start();
mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
}
- // Always play the entire launcher animation when going home, since it is separate from
- // the animation that has been controlled thus far.
- if (mGestureState.getEndTarget() == HOME) {
- start = 0;
- }
-
- // We want to use the same interpolator as the window, but need to adjust it to
- // interpolate over the remaining progress (end - start).
- TimeInterpolator adjustedInterpolator = Interpolators.mapToProgress(
- interpolator, start, end);
- if (mLauncherTransitionController == null) {
- return;
- }
- if (start == end || duration <= 0) {
- mLauncherTransitionController.dispatchSetInterpolator(t -> end);
- } else {
- mLauncherTransitionController.dispatchSetInterpolator(adjustedInterpolator);
- }
- mLauncherTransitionController.getAnimationPlayer().setDuration(Math.max(0, duration));
-
- if (UNSTABLE_SPRINGS.get()) {
- mLauncherTransitionController.dispatchOnStart();
- }
- mLauncherTransitionController.getAnimationPlayer().start();
- mHasLauncherTransitionControllerStarted = true;
}
private void computeRecentsScrollIfInvisible() {
@@ -1221,15 +1189,6 @@
@UiThread
private void startNewTask() {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mRecentsAnimationController.finish(true /* toRecents */, this::startNewTaskInternal);
- } else {
- startNewTaskInternal();
- }
- }
-
- @UiThread
- private void startNewTaskInternal() {
TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
startNewTask(success -> {
if (!success) {
@@ -1270,10 +1229,6 @@
private void cancelCurrentAnimation() {
mCanceled = true;
mCurrentShift.cancelAnimation();
- if (mLauncherTransitionController != null && mLauncherTransitionController
- .getAnimationPlayer().isStarted()) {
- mLauncherTransitionController.getAnimationPlayer().cancel();
- }
}
private void invalidateHandler() {
@@ -1299,7 +1254,10 @@
private void endLauncherTransitionController() {
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
if (mLauncherTransitionController != null) {
- mLauncherTransitionController.getAnimationPlayer().end();
+ // End the animation, but stay at the same visual progress.
+ mLauncherTransitionController.getNormalController().dispatchSetInterpolator(
+ t -> Utilities.boundToRange(mCurrentShift.value, 0, 1));
+ mLauncherTransitionController.getNormalController().getAnimationPlayer().end();
mLauncherTransitionController = null;
}
}
@@ -1581,8 +1539,7 @@
*/
protected void applyWindowTransform() {
if (mWindowTransitionController != null) {
- float progress = mCurrentShift.value / mDragLengthFactor;
- mWindowTransitionController.setPlayFraction(progress);
+ mWindowTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor);
}
if (mRecentsAnimationTargets != null) {
if (mRecentsViewScrollLinked) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
index 9310685..55f5424 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -79,8 +79,8 @@
BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI(
mDeviceState,
wasVisible, (controller) -> {
- controller.dispatchOnStart();
- controller.getAnimationPlayer().end();
+ controller.getNormalController().dispatchOnStart();
+ controller.getNormalController().getAnimationPlayer().end();
});
factory.createActivityInterface(RECENTS_LAUNCH_DURATION);
factory.setRecentsAttachedToAppWindow(true, false);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
index d1da0c1..3898f0b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
@@ -27,11 +27,11 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -84,7 +84,7 @@
/** 6 */
@Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
- boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
+ boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback);
factory.initUI();
return factory;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 5a35eb5..4e38f49 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -39,7 +39,6 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.DiscoveryBounce;
-import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DepthController.ClampedDepthProperty;
@@ -49,6 +48,7 @@
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.views.RecentsView;
@@ -118,7 +118,7 @@
@Override
public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
- boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
+ boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 6f4d34c..5026f36 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -58,6 +58,12 @@
FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get());
return response;
}
+
+ case TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED: {
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ FeatureFlags.ENABLE_OVERVIEW_SHARE.get());
+ return response;
+ }
}
return super.call(method);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
index e54a21c..137f809 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -16,7 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
import android.animation.Animator;
import android.content.Context;
@@ -24,7 +24,6 @@
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
@@ -35,6 +34,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -45,7 +45,6 @@
public abstract class SwipeUpAnimationLogic {
protected static final Rect TEMP_RECT = new Rect();
- private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
protected DeviceProfile mDp;
@@ -66,12 +65,8 @@
protected int mTransitionDragLength;
// How much further we can drag past recents, as a factor of mTransitionDragLength.
protected float mDragLengthFactor = 1;
- // Start resisting when swiping past this factor of mTransitionDragLength.
- private float mDragLengthFactorStartPullback = 1f;
- // This is how far down we can scale down, where 0f is full screen and 1f is recents.
- private float mDragLengthFactorMaxPullback = 1f;
- protected AnimatorPlaybackController mWindowTransitionController;
+ protected AnimatorControllerWithResistance mWindowTransitionController;
public SwipeUpAnimationLogic(Context context, RecentsAnimationDeviceState deviceState,
GestureState gestureState, TransformParams transformParams) {
@@ -97,19 +92,16 @@
if (mDeviceState.isFullyGesturalNavMode()) {
// We can drag all the way to the top of the screen.
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
-
- float startScale = mTaskViewSimulator.getFullScreenScale();
- // Start pulling back when RecentsView scale is 0.75f, and let it go down to 0.5f.
- mDragLengthFactorStartPullback = (0.75f - startScale) / (1 - startScale);
- mDragLengthFactorMaxPullback = (0.5f - startScale) / (1 - startScale);
} else {
- mDragLengthFactor = 1;
- mDragLengthFactorStartPullback = mDragLengthFactorMaxPullback = 1;
+ mDragLengthFactor = 1 + AnimatorControllerWithResistance.TWO_BUTTON_EXTRA_DRAG_FACTOR;
}
PendingAnimation pa = new PendingAnimation(mTransitionDragLength * 2);
- mTaskViewSimulator.addAppToOverviewAnim(pa, t -> t * mDragLengthFactor);
- mWindowTransitionController = pa.createPlaybackController();
+ mTaskViewSimulator.addAppToOverviewAnim(pa, LINEAR);
+ AnimatorPlaybackController normalController = pa.createPlaybackController();
+ mWindowTransitionController = AnimatorControllerWithResistance.createForRecents(
+ normalController, mContext, mTaskViewSimulator.getOrientationState(),
+ mDp, mTaskViewSimulator.recentsViewScale, AnimatedFloat.VALUE);
}
@UiThread
@@ -122,13 +114,6 @@
} else {
float translation = Math.max(displacement, 0);
shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
- if (shift > mDragLengthFactorStartPullback) {
- float pullbackProgress = Utilities.getProgress(shift,
- mDragLengthFactorStartPullback, mDragLengthFactor);
- pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
- shift = mDragLengthFactorStartPullback + pullbackProgress
- * (mDragLengthFactorMaxPullback - mDragLengthFactorStartPullback);
- }
}
mCurrentShift.updateValue(shift);
@@ -183,7 +168,7 @@
HomeAnimationFactory homeAnimationFactory) {
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
- mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor);
+ mCurrentShift.updateValue(startProgress);
mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index a946304..f5f5259 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -101,20 +101,20 @@
}
@Override
- protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) {
+ protected boolean shouldAddStubTaskView(RunningTaskInfo runningTaskInfo) {
if (mHomeTaskInfo != null && runningTaskInfo != null &&
mHomeTaskInfo.taskId == runningTaskInfo.taskId
&& getTaskViewCount() == 0) {
- // Do not add a dummy task if we are running over home with empty recents, so that we
- // show the empty recents message instead of showing a dummy task and later removing it.
+ // Do not add a stub task if we are running over home with empty recents, so that we
+ // show the empty recents message instead of showing a stub task and later removing it.
return false;
}
- return super.shouldAddDummyTaskView(runningTaskInfo);
+ return super.shouldAddStubTaskView(runningTaskInfo);
}
@Override
protected void applyLoadPlan(ArrayList<Task> tasks) {
- // When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
+ // When quick-switching on 3p-launcher, we add a "stub" tile corresponding to Launcher
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
// track the index of the next task appropriately, as if we are switching on any other app.
if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == mRunningTaskId && !tasks.isEmpty()) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index db1948b..7032fae 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -60,7 +60,7 @@
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
/**
- * A dummy input consumer used when the device is still locked, e.g. from secure camera.
+ * A placeholder input consumer used when the device is still locked, e.g. from secure camera.
*/
public class DeviceLockedInputConsumer implements InputConsumer,
RecentsAnimationCallbacks.RecentsAnimationListener, BuilderProxy {
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 dda2c5c..9393e08 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
@@ -849,6 +849,14 @@
taskView.setModalness(mTaskModalness);
}
}
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ // Since we reuse the same mLiveTileTaskViewSimulator in the RecentsView, we need
+ // to reset the params after it settles in Overview from swipe up so that we don't
+ // render with obsolete param values.
+ mLiveTileTaskViewSimulator.fullScreenProgress.value = 0;
+ mLiveTileTaskViewSimulator.recentsViewScale.value = 1;
+ mLiveTileTaskViewSimulator.setOffsetY(0);
+ }
if (mRunningTaskTileHidden) {
setRunningTaskHidden(mRunningTaskTileHidden);
}
@@ -1175,9 +1183,9 @@
}
/**
- * Returns true if we should add a dummy taskView for the running task id
+ * Returns true if we should add a stub taskView for the running task id
*/
- protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) {
+ protected boolean shouldAddStubTaskView(RunningTaskInfo runningTaskInfo) {
return runningTaskInfo != null && getTaskView(runningTaskInfo.taskId) == null;
}
@@ -1188,7 +1196,7 @@
* is called. Also scrolls the view to this task.
*/
public void showCurrentTask(RunningTaskInfo runningTaskInfo) {
- if (shouldAddDummyTaskView(runningTaskInfo)) {
+ if (shouldAddStubTaskView(runningTaskInfo)) {
boolean wasEmpty = getChildCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView = mTaskViewPool.getView();
@@ -1501,6 +1509,13 @@
anim.addOnFrameCallback(this::updateCurveProperties);
}
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get() && getRunningTaskView() == taskView) {
+ anim.addOnFrameCallback(() -> {
+ mLiveTileTaskViewSimulator.setOffsetY(taskView.getTranslationY());
+ redrawLiveTile();
+ });
+ }
+
// Add a tiny bit of translation Z, so that it draws on top of other views
if (animateTaskView) {
taskView.setTranslationZ(0.1f);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index a8d6442..7651dd8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -125,7 +125,7 @@
mDimmingPaintAfterClearing.setColor(Color.BLACK);
mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
- // Initialize with dummy value. It is overridden later by TaskView
+ // Initialize with placeholder value. It is overridden later by TaskView
mFullscreenParams = TEMP_PARAMS.get(context);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 27d84e6..6b7daec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -245,14 +245,14 @@
*/
public WorkspaceItemInfo getItemInfo() {
ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(getTask().key);
- WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
- dummyInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
- dummyInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
- dummyInfo.user = componentKey.user;
- dummyInfo.intent = new Intent().setComponent(componentKey.componentName);
- dummyInfo.title = TaskUtils.getTitle(getContext(), getTask());
- dummyInfo.screenId = getRecentsView().indexOfChild(this);
- return dummyInfo;
+ WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
+ stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
+ stubInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
+ stubInfo.user = componentKey.user;
+ stubInfo.intent = new Intent().setComponent(componentKey.componentName);
+ stubInfo.title = TaskUtils.getTitle(getContext(), getTask());
+ stubInfo.screenId = getRecentsView().indexOfChild(this);
+ return stubInfo;
}
@Override
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java b/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java
index c148a4b..7049af0 100644
--- a/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java
+++ b/quickstep/robolectric_tests/src/com/android/quickstep/RecentsActivityTest.java
@@ -60,9 +60,9 @@
FallbackRecentsView frv = activity.getOverviewPanel();
- RunningTaskInfo dummyTask = new RunningTaskInfo();
- dummyTask.taskId = 22;
- frv.showCurrentTask(dummyTask);
+ RunningTaskInfo placeholderTask = new RunningTaskInfo();
+ placeholderTask.taskId = 22;
+ frv.showCurrentTask(placeholderTask);
doLayout(activity);
ThumbnailData thumbnailData = new ThumbnailData();
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index bd97f65..f3d5434 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -45,7 +45,6 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
-import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -55,7 +54,6 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
@@ -94,7 +92,6 @@
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
* home and/or all-apps. Not used for 3p launchers.
*/
-@TargetApi(Build.VERSION_CODES.O)
@SuppressWarnings("unused")
public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTransitionManager
implements OnDeviceProfileChangeListener {
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index f42b124..cc7b712 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -43,9 +43,11 @@
import android.util.Log;
import androidx.annotation.MainThread;
+import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.RemoteActionShortcut;
import com.android.launcher3.popup.SystemShortcut;
@@ -57,6 +59,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.Consumer;
/**
* Data model for digital wellbeing status of apps.
@@ -72,6 +75,9 @@
private static final int MSG_FULL_REFRESH = 3;
// Welbeing contract
+ private static final String PATH_ACTIONS = "actions";
+ private static final String PATH_MINIMAL_DEVICE = "minimal_device";
+ private static final String METHOD_GET_MINIMAL_DEVICE_CONFIG = "get_minimal_device_config";
private static final String METHOD_GET_ACTIONS = "get_actions";
private static final String EXTRA_ACTIONS = "actions";
private static final String EXTRA_ACTION = "action";
@@ -104,15 +110,22 @@
mContentObserver = new ContentObserver(MAIN_EXECUTOR.getHandler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
- // Wellbeing reports that app actions have changed.
if (DEBUG || mIsInTest) {
- Log.d(TAG, "ContentObserver.onChange() called with: selfChange = [" + selfChange
- + "], uri = [" + uri + "]");
+ Log.d(TAG, "ContentObserver.onChange() called with: selfChange = ["
+ + selfChange + "], uri = [" + uri + "]");
}
Preconditions.assertUIThread();
- updateWellbeingData();
+
+ if (uri.getPath().contains(PATH_ACTIONS)) {
+ // Wellbeing reports that app actions have changed.
+ updateWellbeingData();
+ } else if (uri.getPath().contains(PATH_MINIMAL_DEVICE)) {
+ // Wellbeing reports that minimal device state or config is changed.
+ updateLauncherModel();
+ }
}
};
+ FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, this::updateLauncherModel);
if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
context.registerReceiver(
@@ -146,14 +159,18 @@
private void restartObserver() {
final ContentResolver resolver = mContext.getContentResolver();
resolver.unregisterContentObserver(mContentObserver);
- Uri actionsUri = apiBuilder().path("actions").build();
+ Uri actionsUri = apiBuilder().path(PATH_ACTIONS).build();
+ Uri minimalDeviceUri = apiBuilder().path(PATH_MINIMAL_DEVICE).build();
try {
resolver.registerContentObserver(
actionsUri, true /* notifyForDescendants */, mContentObserver);
+ resolver.registerContentObserver(
+ minimalDeviceUri, true /* notifyForDescendants */, mContentObserver);
} catch (Exception e) {
Log.e(TAG, "Failed to register content observer for " + actionsUri + ": " + e);
if (mIsInTest) throw new RuntimeException(e);
}
+
updateWellbeingData();
}
@@ -191,12 +208,42 @@
mWorkerHandler.sendEmptyMessage(MSG_FULL_REFRESH);
}
+ private void updateLauncherModel() {
+ if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) return;
+
+ // TODO: init Launcher in minimal device / normal mode
+ }
+
private Uri.Builder apiBuilder() {
return new Uri.Builder()
.scheme(SCHEME_CONTENT)
.authority(mWellbeingProviderPkg + ".api");
}
+ /**
+ * Fetch most up-to-date minimal device config.
+ */
+ @WorkerThread
+ private void runWithMinimalDeviceConfigs(Consumer<Bundle> consumer) {
+ if (DEBUG || mIsInTest) {
+ Log.d(TAG, "runWithMinimalDeviceConfigs() called");
+ }
+ Preconditions.assertNonUiThread();
+
+ final Uri contentUri = apiBuilder().build();
+ final Bundle remoteBundle;
+ try (ContentProviderClient client = mContext.getContentResolver()
+ .acquireUnstableContentProviderClient(contentUri)) {
+ remoteBundle = client.call(
+ METHOD_GET_MINIMAL_DEVICE_CONFIG, null /* args */, null /* extras */);
+ consumer.accept(remoteBundle);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to retrieve data from " + contentUri + ": " + e);
+ if (mIsInTest) throw new RuntimeException(e);
+ }
+ if (DEBUG || mIsInTest) Log.i(TAG, "runWithMinimalDeviceConfigs(): finished");
+ }
+
private boolean updateActions(String... packageNames) {
if (packageNames.length == 0) {
return true;
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 9dc2132..a9a4e95 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -52,6 +52,7 @@
import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.quickstep.views.RecentsView;
@@ -106,7 +107,7 @@
public abstract void onAssistantVisibilityChanged(float visibility);
public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
- boolean activityVisible, Consumer<AnimatorPlaybackController> callback);
+ boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
public abstract ActivityInitListener createActivityInitListener(
Predicate<Boolean> onInitListener);
@@ -312,11 +313,11 @@
protected final ACTIVITY_TYPE mActivity;
private final STATE_TYPE mStartState;
- private final Consumer<AnimatorPlaybackController> mCallback;
+ private final Consumer<AnimatorControllerWithResistance> mCallback;
private boolean mIsAttachedToWindow;
- DefaultAnimationFactory(Consumer<AnimatorPlaybackController> callback) {
+ DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
mCallback = callback;
mActivity = getCreatedActivity();
@@ -344,7 +345,13 @@
controller.setEndAction(() -> mActivity.getStateManager().goToState(
controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState,
false));
- mCallback.accept(controller);
+
+ RecentsView recentsView = mActivity.getOverviewPanel();
+ AnimatorControllerWithResistance controllerWithResistance =
+ AnimatorControllerWithResistance.createForRecents(controller, mActivity,
+ recentsView.getPagedViewOrientedState(), mActivity.getDeviceProfile(),
+ recentsView, RECENTS_SCALE_PROPERTY);
+ mCallback.accept(controllerWithResistance);
// Creating the activity controller animation sometimes reapplies the launcher state
// (because we set the animation as the current state animation), so we reapply the
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 0710a0a..b2bce0c 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -374,7 +374,7 @@
StringBuilder regions = new StringBuilder(" currentTouchableRotations=");
for(int i = 0; i < mSwipeTouchRegions.size(); i++) {
OrientationRectF rectF = mSwipeTouchRegions.get(mSwipeTouchRegions.keyAt(i));
- regions.append(rectF.mRotation).append(" ");
+ regions.append(rectF).append(" ");
}
pw.println(regions.toString());
pw.println(" mNavBarGesturalHeight=" + mNavBarGesturalHeight);
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 6f54ba2..6c302ae 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -160,9 +160,9 @@
@Override
public void onTaskRemoved(int taskId) {
- Task.TaskKey dummyKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
- mThumbnailCache.remove(dummyKey);
- mIconCache.onTaskRemoved(dummyKey);
+ Task.TaskKey stubKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
+ mThumbnailCache.remove(stubKey);
+ mIconCache.onTaskRemoved(stubKey);
}
public void onTrimMemory(int level) {
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 044e010..60d8ef6 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -184,8 +184,7 @@
@Override
public void updateFinalShift() {
- float progress = mCurrentShift.value / mDragLengthFactor;
- mWindowTransitionController.setPlayFraction(progress);
+ mWindowTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor);
mTaskViewSimulator.apply(mTransformParams);
}
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
new file mode 100644
index 0000000..d58329a
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2020 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.util;
+
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
+
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.util.FloatProperty;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.quickstep.LauncherActivityInterface;
+import com.android.quickstep.SysUINavigationMode;
+
+/**
+ * Controls an animation that can go beyond progress = 1, at which point resistance should be
+ * applied. Internally, this is a wrapper around 2 {@link AnimatorPlaybackController}s, one that
+ * runs from progress 0 to 1 like normal, then one that seamlessly continues that animation but
+ * starts applying resistance as well.
+ */
+public class AnimatorControllerWithResistance {
+
+ /**
+ * How much farther we can drag past overview in 2-button mode, as a factor of the distance
+ * it takes to drag from an app to overview.
+ */
+ public static final float TWO_BUTTON_EXTRA_DRAG_FACTOR = 0.25f;
+
+ /**
+ * Start slowing down the rate of scaling down when recents view is smaller than this scale.
+ */
+ private static final float RECENTS_SCALE_START_RESIST = 0.75f;
+
+ /**
+ * Recents view will reach this scale at the very end of the drag.
+ */
+ private static final float RECENTS_SCALE_MAX_RESIST = 0.5f;
+
+ private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL;
+
+ private final AnimatorPlaybackController mNormalController;
+ private final AnimatorPlaybackController mResistanceController;
+
+ // Initialize to -1 so the first 0 gets applied.
+ private float mLastNormalProgress = -1;
+ private float mLastResistProgress;
+
+ public AnimatorControllerWithResistance(AnimatorPlaybackController normalController,
+ AnimatorPlaybackController resistanceController) {
+ mNormalController = normalController;
+ mResistanceController = resistanceController;
+ }
+
+ public AnimatorPlaybackController getNormalController() {
+ return mNormalController;
+ }
+
+ /**
+ * Applies the current progress of the animation.
+ * @param progress From 0 to maxProgress, where 1 is the target we are animating towards.
+ * @param maxProgress > 1, this is where the resistance will be applied.
+ */
+ public void setProgress(float progress, float maxProgress) {
+ float normalProgress = Utilities.boundToRange(progress, 0, 1);
+ if (normalProgress != mLastNormalProgress) {
+ mLastNormalProgress = normalProgress;
+ mNormalController.setPlayFraction(normalProgress);
+ }
+ if (maxProgress <= 1) {
+ return;
+ }
+ float resistProgress = progress <= 1 ? 0 : Utilities.getProgress(progress, 1, maxProgress);
+ if (resistProgress != mLastResistProgress) {
+ mLastResistProgress = resistProgress;
+ mResistanceController.setPlayFraction(resistProgress);
+ }
+ }
+
+ /**
+ * Applies resistance to recents when swiping up past its target position.
+ * @param normalController The controller to run from 0 to 1 before this resistance applies.
+ * @param context Used to compute start and end values.
+ * @param recentsOrientedState Used to compute start and end values.
+ * @param dp Used to compute start and end values.
+ * @param scaleTarget The target for the scaleProperty.
+ * @param scaleProperty Animate the value to change the scale of the window/recents view.
+ */
+ public static <SCALE> AnimatorControllerWithResistance createForRecents(
+ AnimatorPlaybackController normalController, Context context,
+ RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget,
+ FloatProperty<SCALE> scaleProperty) {
+ Rect startRect = new Rect();
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect,
+ recentsOrientedState.getOrientationHandler());
+ long distanceToCover = startRect.bottom;
+ boolean isTwoButtonMode = SysUINavigationMode.getMode(context) == TWO_BUTTONS;
+ if (isTwoButtonMode) {
+ // We can only drag a small distance past overview, not to the top of the screen.
+ distanceToCover = (long)
+ ((dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR);
+ }
+ PendingAnimation resistAnim = new PendingAnimation(distanceToCover * 2);
+
+ PointF pivot = new PointF();
+ float fullscreenScale = recentsOrientedState.getFullScreenScaleAndPivot(
+ startRect, dp, pivot);
+ float startScale = 1;
+ float prevScaleRate = (fullscreenScale - startScale) / (dp.heightPx - startRect.bottom);
+ // This is what the scale would be at the end of the drag if we didn't apply resistance.
+ float endScale = startScale - prevScaleRate * distanceToCover;
+ final TimeInterpolator scaleInterpolator;
+ if (isTwoButtonMode) {
+ // We are bounded by the distance of the drag, so we don't need to apply resistance.
+ scaleInterpolator = LINEAR;
+ } else {
+ // Create an interpolator that resists the scale so the scale doesn't get smaller than
+ // RECENTS_SCALE_MAX_RESIST.
+ float startResist = Utilities.getProgress(RECENTS_SCALE_START_RESIST, startScale,
+ endScale);
+ float maxResist = Utilities.getProgress(RECENTS_SCALE_MAX_RESIST, startScale, endScale);
+ scaleInterpolator = t -> {
+ if (t < startResist) {
+ return t;
+ }
+ float resistProgress = Utilities.getProgress(t, startResist, 1);
+ resistProgress = RECENTS_SCALE_RESIST_INTERPOLATOR.getInterpolation(resistProgress);
+ return startResist + resistProgress * (maxResist - startResist);
+ };
+ }
+ resistAnim.addFloat(scaleTarget, scaleProperty, startScale, endScale,
+ scaleInterpolator);
+
+ AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController();
+ return new AnimatorControllerWithResistance(normalController, resistanceController);
+ }
+
+}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index a5d4568..969fa50 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -358,18 +358,23 @@
if (count < 3) {
// Too few samples
- if (count == 2) {
- int endPos = pointPos - 1;
- if (endPos < 0) {
- endPos += HISTORY_SIZE;
+ switch (count) {
+ case 2: {
+ int endPos = pointPos - 1;
+ if (endPos < 0) {
+ endPos += HISTORY_SIZE;
+ }
+ float denominator = eventTime - mHistoricTimes[endPos];
+ if (denominator != 0) {
+ return (mHistoricPos[pointPos] - mHistoricPos[endPos]) / denominator;
+ }
}
- float denominator = eventTime - mHistoricTimes[endPos];
- if (denominator != 0) {
- return (eventTime - mHistoricPos[endPos]) / denominator;
-
- }
+ // fall through
+ case 1:
+ return 0f;
+ default:
+ return null;
}
- return null;
}
float Sxx = sxi2 - sxi * sxi / count;
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index bf093fd..ecd4e2b 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -36,6 +36,7 @@
import com.android.launcher3.tapl.Background;
import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
import com.android.launcher3.tapl.Overview;
+import com.android.launcher3.tapl.OverviewActions;
import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.ui.TaplTestsLauncher3;
@@ -68,11 +69,14 @@
});
}
- private void startTestApps() throws Exception {
+ public static void startTestApps() throws Exception {
startAppFast(getAppPackageName());
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
startTestActivity(2);
+ }
+ private void startTestAppsWithCheck() throws Exception {
+ startTestApps();
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
@@ -105,7 +109,7 @@
@Test
@PortraitLandscape
public void testOverview() throws Exception {
- startTestApps();
+ startTestAppsWithCheck();
// mLauncher.pressHome() also tests an important case of pressing home while in background.
Overview overview = mLauncher.pressHome().switchToOverview();
assertTrue("Launcher internal state didn't switch to Overview",
@@ -189,6 +193,22 @@
0, getTaskCount(launcher)));
}
+ /**
+ * Smoke test for action buttons: Presses all the buttons and makes sure no crashes occur.
+ */
+ @Test
+ @NavigationModeSwitch
+ @PortraitLandscape
+ public void testOverviewActions() throws Exception {
+ if (mLauncher.getNavigationModel() != NavigationModel.TWO_BUTTON) {
+ startTestAppsWithCheck();
+ OverviewActions actionsView =
+ mLauncher.pressHome().switchToOverview().getOverviewActions();
+ actionsView.clickAndDismissScreenshot();
+ actionsView.clickAndDismissShare();
+ }
+ }
+
private int getCurrentOverviewPage(Launcher launcher) {
return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
}
diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
index 115294a..72116eb 100644
--- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
+++ b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
@@ -71,7 +71,7 @@
/**
* Test to verify view inflation does not happen during swipe up.
- * To verify view inflation, we setup a dummy ViewConfiguration and check if any call to that class
+ * To verify view inflation, we setup a stub ViewConfiguration and check if any call to that class
* does from a View.init method or not.
*
* Alternative approaches considered:
@@ -138,13 +138,13 @@
@Test
@NavigationModeSwitch(mode = ZERO_BUTTON)
public void testSwipeUpFromApp_widget_update() {
- String dummyText = "Some random dummy text";
+ String stubText = "Some random stub text";
executeSwipeUpTestWithWidget(
widgetId -> { },
widgetId -> AppWidgetManager.getInstance(getContext())
- .updateAppWidget(widgetId, createMainWidgetViews(dummyText)),
- dummyText);
+ .updateAppWidget(widgetId, createMainWidgetViews(stubText)),
+ stubText);
}
@Test
diff --git a/res/animator-v23/discovery_bounce.xml b/res/animator-v23/discovery_bounce.xml
deleted file mode 100644
index f554853..0000000
--- a/res/animator-v23/discovery_bounce.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, 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.
-*/
--->
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:duration="2166"
- android:repeatCount="5">
- <propertyValuesHolder
- android:propertyName="progress"
- android:valueType="floatType">
- <keyframe
- android:fraction="0"
- android:value="1f" />
- <keyframe
- android:fraction="0.246"
- android:value="1f" />
- <keyframe
- android:fraction=".423"
- android:interpolator="@interpolator/disco_bounce"
- android:value="0.9738f" />
- <keyframe
- android:fraction="0.754"
- android:interpolator="@interpolator/disco_bounce"
- android:value="1f" />
- <keyframe
- android:fraction="1"
- android:value="1f" />
- </propertyValuesHolder>
-</objectAnimator>
diff --git a/res/animator/discovery_bounce.xml b/res/animator/discovery_bounce.xml
index f02ebdb..f554853 100644
--- a/res/animator/discovery_bounce.xml
+++ b/res/animator/discovery_bounce.xml
@@ -16,20 +16,28 @@
** limitations under the License.
*/
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="sequentially">
- <objectAnimator
- android:duration="166"
- android:interpolator="@interpolator/disco_bounce"
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="2166"
+ android:repeatCount="5">
+ <propertyValuesHolder
android:propertyName="progress"
- android:startOffset="750"
- android:valueFrom="1f"
- android:valueTo="0.9438f"
- android:valueType="floatType" />
- <objectAnimator
- android:duration="500"
- android:interpolator="@interpolator/disco_bounce"
- android:propertyName="progress"
- android:valueTo="1f"
- android:valueType="floatType" />
-</set>
+ android:valueType="floatType">
+ <keyframe
+ android:fraction="0"
+ android:value="1f" />
+ <keyframe
+ android:fraction="0.246"
+ android:value="1f" />
+ <keyframe
+ android:fraction=".423"
+ android:interpolator="@interpolator/disco_bounce"
+ android:value="0.9738f" />
+ <keyframe
+ android:fraction="0.754"
+ android:interpolator="@interpolator/disco_bounce"
+ android:value="1f" />
+ <keyframe
+ android:fraction="1"
+ android:value="1f" />
+ </propertyValuesHolder>
+</objectAnimator>
diff --git a/res/color-v24/all_apps_bg_hand_fill.xml b/res/color/all_apps_bg_hand_fill.xml
similarity index 100%
rename from res/color-v24/all_apps_bg_hand_fill.xml
rename to res/color/all_apps_bg_hand_fill.xml
diff --git a/res/color-v24/all_apps_bg_hand_fill_dark.xml b/res/color/all_apps_bg_hand_fill_dark.xml
similarity index 100%
rename from res/color-v24/all_apps_bg_hand_fill_dark.xml
rename to res/color/all_apps_bg_hand_fill_dark.xml
diff --git a/res/drawable-v26/ic_deepshortcut_placeholder.xml b/res/drawable-v26/ic_deepshortcut_placeholder.xml
deleted file mode 100644
index 3fa8506..0000000
--- a/res/drawable-v26/ic_deepshortcut_placeholder.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 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.
--->
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="?attr/popupColorSecondary"/>
- <foreground android:drawable="?attr/popupColorSecondary"/>
-</adaptive-icon>
diff --git a/res/drawable-v26/ic_launcher_home.xml b/res/drawable-v26/ic_launcher_home.xml
deleted file mode 100644
index 7038775..0000000
--- a/res/drawable-v26/ic_launcher_home.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@color/icon_background" />
- <foreground>
- <bitmap android:src="@mipmap/ic_launcher_home_foreground"/>
- </foreground>
-</adaptive-icon>
diff --git a/res/drawable-v24/ic_block_shadow.xml b/res/drawable/ic_block_shadow.xml
similarity index 100%
rename from res/drawable-v24/ic_block_shadow.xml
rename to res/drawable/ic_block_shadow.xml
diff --git a/res/drawable/ic_deepshortcut_placeholder.xml b/res/drawable/ic_deepshortcut_placeholder.xml
index 85a9694..3fa8506 100644
--- a/res/drawable/ic_deepshortcut_placeholder.xml
+++ b/res/drawable/ic_deepshortcut_placeholder.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!--
+ Copyright (C) 2017 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.
@@ -13,10 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="?attr/popupColorSecondary" />
- <size
- android:height="32dp"
- android:width="32dp" />
-</shape>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="?attr/popupColorSecondary"/>
+ <foreground android:drawable="?attr/popupColorSecondary"/>
+</adaptive-icon>
diff --git a/res/drawable/ic_launcher_home.xml b/res/drawable/ic_launcher_home.xml
index a6f2519..7038775 100644
--- a/res/drawable/ic_launcher_home.xml
+++ b/res/drawable/ic_launcher_home.xml
@@ -13,6 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<bitmap
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@mipmap/ic_launcher_home" />
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/icon_background" />
+ <foreground>
+ <bitmap android:src="@mipmap/ic_launcher_home_foreground"/>
+ </foreground>
+</adaptive-icon>
diff --git a/res/drawable-v24/ic_remove_shadow.xml b/res/drawable/ic_remove_shadow.xml
similarity index 100%
rename from res/drawable-v24/ic_remove_shadow.xml
rename to res/drawable/ic_remove_shadow.xml
diff --git a/res/drawable-v24/ic_setup_shadow.xml b/res/drawable/ic_setup_shadow.xml
similarity index 100%
rename from res/drawable-v24/ic_setup_shadow.xml
rename to res/drawable/ic_setup_shadow.xml
diff --git a/res/drawable-v24/ic_uninstall_shadow.xml b/res/drawable/ic_uninstall_shadow.xml
similarity index 100%
rename from res/drawable-v24/ic_uninstall_shadow.xml
rename to res/drawable/ic_uninstall_shadow.xml
diff --git a/res/layout/search_section_title.xml b/res/layout/search_section_title.xml
index 9ab27c1..c39a641 100644
--- a/res/layout/search_section_title.xml
+++ b/res/layout/search_section_title.xml
@@ -19,7 +19,5 @@
android:fontFamily="@style/TextHeadline"
android:layout_width="wrap_content"
android:textColor="?android:attr/textColorPrimary"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:paddingTop="8dp"
+ android:padding="4dp"
android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/res/mipmap-hdpi/ic_launcher_home.png b/res/mipmap-hdpi/ic_launcher_home.png
deleted file mode 100644
index d068d92..0000000
--- a/res/mipmap-hdpi/ic_launcher_home.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_home.png b/res/mipmap-mdpi/ic_launcher_home.png
deleted file mode 100644
index 16c8ec2..0000000
--- a/res/mipmap-mdpi/ic_launcher_home.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_home.png b/res/mipmap-xhdpi/ic_launcher_home.png
deleted file mode 100644
index 8b2671b..0000000
--- a/res/mipmap-xhdpi/ic_launcher_home.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_home.png b/res/mipmap-xxhdpi/ic_launcher_home.png
deleted file mode 100644
index 43d8b7d..0000000
--- a/res/mipmap-xxhdpi/ic_launcher_home.png
+++ /dev/null
Binary files differ
diff --git a/res/values-night-v26/styles.xml b/res/values-night/styles.xml
similarity index 100%
rename from res/values-night-v26/styles.xml
rename to res/values-night/styles.xml
diff --git a/res/values-v22/styles.xml b/res/values-v22/styles.xml
deleted file mode 100644
index f86db7a..0000000
--- a/res/values-v22/styles.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* 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.
-*/
--->
-
-<resources>
-
- <style name="AppItemActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
- <item name="widgetsTheme">@style/WidgetContainerTheme</item>
- </style>
-
-</resources>
\ No newline at end of file
diff --git a/res/values-v26/bools.xml b/res/values-v26/bools.xml
deleted file mode 100644
index ad8c7a1..0000000
--- a/res/values-v26/bools.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2017, 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.
-*/
--->
-
-<resources>
- <bool name="notification_dots_enabled">true</bool>
-
- <bool name="enable_install_shortcut_api">false</bool>
-</resources>
\ No newline at end of file
diff --git a/res/values-v26/styles.xml b/res/values-v26/styles.xml
deleted file mode 100644
index d2f0802..0000000
--- a/res/values-v26/styles.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2017 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.
-*/
--->
-<resources>
- <!-- Theme for the widget container. -->
- <style name="WidgetContainerTheme" parent="@android:style/Theme.DeviceDefault.Settings">
- <item name="android:colorPrimaryDark">#E8EAED</item>
- <item name="android:textColorSecondary">?android:attr/textColorPrimary</item>
- <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
- </style>
- <style name="WidgetContainerTheme.Dark" parent="AppTheme.Dark">
- <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
- <item name="android:colorPrimaryDark">#616161</item> <!-- Gray 700 -->
- </style>
-
-</resources>
diff --git a/res/values/bools.xml b/res/values/bools.xml
deleted file mode 100644
index bc2c678..0000000
--- a/res/values/bools.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2017, 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.
-*/
--->
-
-<resources>
- <bool name="notification_dots_enabled">false</bool>
-
- <bool name="enable_install_shortcut_api">true</bool>
-</resources>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 043ad9a..ad607a3 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -37,6 +37,7 @@
<color name="all_apps_bg_hand_fill">#E5E5E5</color>
<color name="all_apps_bg_hand_fill_dark">#9AA0A6</color>
+ <color name="all_apps_section_fill">#327d7d7d</color>
<color name="gesture_tutorial_ripple_color">#A0C2F9</color> <!-- Light Blue -->
<color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
diff --git a/res/values/drawables.xml b/res/values/drawables.xml
deleted file mode 100644
index 9c57ec1..0000000
--- a/res/values/drawables.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<resources>
- <drawable name="ic_setup_shadow">@drawable/ic_setting</drawable>
- <drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
- <drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
- <drawable name="ic_block_shadow">@drawable/ic_block_no_shadow</drawable>
-</resources>
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3b9532e..fd3d873 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -143,7 +143,7 @@
<style name="AppTheme.Dark.DarkMainColor" parent="@style/LauncherTheme.Dark.DarkMainColor" />
<style name="AppTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark.DarkText" />
- <style name="AppItemActivityTheme" parent="@android:style/Theme.Material.Light.Dialog.Alert">
+ <style name="AppItemActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
</style>
@@ -171,14 +171,16 @@
<item name="android:textColorSecondary">?attr/workspaceTextColor</item>
</style>
- <!-- Theme for the widget container. Overridden on API 26. -->
+ <!-- Theme for the widget container. -->
<style name="WidgetContainerTheme" parent="@android:style/Theme.DeviceDefault.Settings">
- <item name="android:colorEdgeEffect">?android:attr/textColorSecondaryInverse</item>
- <item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
- <item name="android:textColorSecondary">?android:attr/textColorSecondaryInverse</item>
+ <item name="android:colorPrimaryDark">#E8EAED</item>
+ <item name="android:textColorSecondary">?android:attr/textColorPrimary</item>
+ <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
</style>
-
- <style name="WidgetContainerTheme.Dark" />
+ <style name="WidgetContainerTheme.Dark" parent="AppTheme.Dark">
+ <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
+ <item name="android:colorPrimaryDark">#616161</item> <!-- Gray 700 -->
+ </style>
<style name="FastScrollerPopup" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
<item name="android:layout_width">wrap_content</item>
diff --git a/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index 5610b0e..9ac3fe7 100644
--- a/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -53,10 +53,10 @@
mModelHelper = new LauncherModelHelper();
mModelHelper.initializeData("/cache_data_updated_task_data.txt");
- // Add dummy entries in the cache to simulate update
+ // Add placeholder entries in the cache to simulate update
Context context = RuntimeEnvironment.application;
IconCache iconCache = LauncherAppState.getInstance(context).getIconCache();
- CachingLogic<ItemInfo> dummyLogic = new CachingLogic<ItemInfo>() {
+ CachingLogic<ItemInfo> placeholderLogic = new CachingLogic<ItemInfo>() {
@Override
public ComponentName getComponent(ItemInfo info) {
return info.getTargetComponent();
@@ -81,7 +81,7 @@
UserManager um = context.getSystemService(UserManager.class);
for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- iconCache.addIconToDBAndMemCache(info, dummyLogic, new PackageInfo(),
+ iconCache.addIconToDBAndMemCache(info, placeholderLogic, new PackageInfo(),
um.getSerialNumberForUser(info.user), true);
}
}
diff --git a/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
index bbbe21e..be03c7d 100644
--- a/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
@@ -165,7 +165,7 @@
@Override
public void onOpen(SQLiteDatabase db) { }
};
- // Insert dummy data
+ // Insert mock data
for (int i = 0; i < 10; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
diff --git a/robolectric_tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java b/robolectric_tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java
index 8f3a83e..655237d 100644
--- a/robolectric_tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/DefaultLayoutProviderTest.java
@@ -109,7 +109,7 @@
public void testCustomProfileLoaded_with_widget() throws Exception {
String pendingAppPkg = "com.test.pending";
- // Add a dummy session info so that the widget exists
+ // Add a placeholder session info so that the widget exists
SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
params.setAppPackageName(pendingAppPkg);
@@ -120,7 +120,7 @@
setField(sessionInfo, "appIcon", BitmapInfo.LOW_RES_ICON);
writeLayoutAndLoad(new LauncherLayoutBuilder().atWorkspace(0, 1, 0)
- .putWidget(pendingAppPkg, "DummyWidget", 2, 2));
+ .putWidget(pendingAppPkg, "PlaceholderWidget", 2, 2));
// Verify widget
assertEquals(1, mModelHelper.getBgDataModel().appWidgets.size());
diff --git a/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java b/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 3a252dc..0e760f9 100644
--- a/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -110,7 +110,7 @@
public void getAppShortcutInfo_dontAllowMissing_invalidComponent() {
initCursor(ITEM_TYPE_APPLICATION, "");
assertTrue(mLoaderCursor.moveToNext());
- ComponentName cn = new ComponentName(mContext.getPackageName(), "dummy-do");
+ ComponentName cn = new ComponentName(mContext.getPackageName(), "placeholder-do");
assertNull(mLoaderCursor.getAppShortcutInfo(
new Intent().setComponent(cn), false /* allowMissingTarget */, true));
}
@@ -136,7 +136,7 @@
initCursor(ITEM_TYPE_APPLICATION, "");
assertTrue(mLoaderCursor.moveToNext());
- ComponentName cn = new ComponentName(mContext.getPackageName(), "dummy-do");
+ ComponentName cn = new ComponentName(mContext.getPackageName(), "placeholder-do");
WorkspaceItemInfo info = Executors.MODEL_EXECUTOR.submit(() ->
mLoaderCursor.getAppShortcutInfo(
new Intent().setComponent(cn), true /* allowMissingTarget */, true))
diff --git a/robolectric_tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/robolectric_tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index ee73b82..4184d33 100644
--- a/robolectric_tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -44,7 +44,7 @@
@Test
public void testMigrateProfileId() throws Exception {
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
- // Add some dummy data
+ // Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
@@ -64,7 +64,7 @@
@Test
public void testChangeDefaultColumn() throws Exception {
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
- // Add some dummy data
+ // Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java b/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 0388087..f2b3071 100644
--- a/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -81,7 +81,7 @@
public static final int NO__ICON = -1;
public static final String TEST_PACKAGE = "com.android.launcher3.validpackage";
- // Authority for providing a dummy default-workspace-layout data.
+ // Authority for providing a test default-workspace-layout data.
private static final String TEST_PROVIDER_AUTHORITY =
LauncherModelHelper.class.getName().toLowerCase();
private static final int DEFAULT_BITMAP_SIZE = 10;
@@ -252,7 +252,7 @@
}
/**
- * Adds a dummy item in the DB.
+ * Adds a mock item in the DB.
* @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
* folder (where the type represents the number of items in the folder).
*/
@@ -310,7 +310,7 @@
}
/**
- * Initializes the DB with dummy elements to represent the provided grid structure.
+ * Initializes the DB with mock elements to represent the provided grid structure.
* @param typeArray A 3d array of item types. {@see #addItem(int, long, long, int, int)} for
* type definitions. The first dimension represents the screens and the next
* two represent the workspace grid.
@@ -347,7 +347,7 @@
}
/**
- * Sets up a dummy provider to load the provided layout by default, next time the layout loads
+ * Sets up a mock provider to load the provided layout by default, next time the layout loads
*/
public LauncherModelHelper setupDefaultLayoutProvider(LauncherLayoutBuilder builder)
throws Exception {
@@ -360,7 +360,7 @@
"launcher3.layout.provider", TEST_PROVIDER_AUTHORITY);
shadowOf(context.getPackageManager())
- .addProviderIfNotPresent(new ComponentName("com.test", "Dummy")).authority =
+ .addProviderIfNotPresent(new ComponentName("com.test", "Mock")).authority =
TEST_PROVIDER_AUTHORITY;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
diff --git a/robolectric_tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java b/robolectric_tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java
index 84c65b1..5ab3106 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java
@@ -129,7 +129,7 @@
ShadowPackageManager spm = shadowOf(mContext.getPackageManager());
for (int i = 0; i < num; i++) {
- ComponentName cn = new ComponentName("com.dummy.apk" + i, "DummyWidet");
+ ComponentName cn = new ComponentName("com.placeholder.apk" + i, "PlaceholderWidet");
AppWidgetProviderInfo widgetInfo = new AppWidgetProviderInfo();
widgetInfo.provider = cn;
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index ce37a30..3bfe379 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import static android.animation.ValueAnimator.areAnimatorsEnabled;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
@@ -126,7 +127,7 @@
}
public final void close(boolean animate) {
- animate &= Utilities.areAnimationsEnabled(getContext());
+ animate &= areAnimatorsEnabled();
if (mIsOpen) {
BaseActivity.fromContext(getContext()).getUserEventDispatcher()
.resetElapsedContainerMillis("container closed");
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 89d768c..1cd201f 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.animation.ValueAnimator.areAnimatorsEnabled;
+
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
import android.animation.Animator;
@@ -2009,7 +2011,7 @@
// Animations are disabled in power save mode, causing the repeated animation to jump
// spastically between beginning and end states. Since this looks bad, we don't repeat
// the animation in power save mode.
- if (Utilities.areAnimationsEnabled(getContext())) {
+ if (areAnimatorsEnabled()) {
va.setRepeatMode(ValueAnimator.REVERSE);
va.setRepeatCount(ValueAnimator.INFINITE);
}
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 62c9b4d..be6adc7 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -20,7 +20,6 @@
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -69,7 +68,7 @@
import java.util.List;
import java.util.Set;
-public class InstallShortcutReceiver extends BroadcastReceiver {
+public class InstallShortcutReceiver {
public static final int FLAG_ACTIVITY_PAUSED = 1;
public static final int FLAG_LOADER_RUNNING = 2;
@@ -82,9 +81,6 @@
private static final String TAG = "InstallShortcutReceiver";
private static final boolean DBG = false;
- private static final String ACTION_INSTALL_SHORTCUT =
- "com.android.launcher.action.INSTALL_SHORTCUT";
-
private static final String LAUNCH_INTENT_KEY = "intent.launch";
private static final String NAME_KEY = "name";
private static final String ICON_KEY = "icon";
@@ -188,25 +184,6 @@
sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
- public void onReceive(Context context, Intent data) {
- if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
- return;
- }
- PendingInstallShortcutInfo info = createPendingInfo(context, data);
- if (info != null) {
- if (!info.isLauncherActivity()) {
- // Since its a custom shortcut, verify that it is safe to launch.
- if (!new PackageManagerHelper(context).hasPermissionForActivity(
- info.launchIntent, null)) {
- // Target cannot be launched, or requires some special permission to launch
- Log.e(TAG, "Ignoring malicious intent " + info.launchIntent.toUri(0));
- return;
- }
- }
- queuePendingShortcutInfo(info, context);
- }
- }
-
/**
* @return true is the extra is either null or is of type {@param type}
*/
@@ -251,6 +228,10 @@
queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, widgetId, context), context);
}
+ public static void queueApplication(LauncherActivityInfo info, Context context) {
+ queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
+ }
+
public static void queueApplication(Intent data, UserHandle user, Context context) {
queuePendingShortcutInfo(new PendingInstallShortcutInfo(data, context, user),
context);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index db1f1b0..f87c344 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1196,11 +1196,8 @@
int[] cellXY = mTmpAddItemCellCoordinates;
CellLayout layout = getCellLayout(container, screenId);
- WorkspaceItemInfo info = null;
- if (Utilities.ATLEAST_OREO) {
- info = PinRequestHelper.createWorkspaceItemFromPinItemRequest(
+ WorkspaceItemInfo info = PinRequestHelper.createWorkspaceItemFromPinItemRequest(
this, PinRequestHelper.getPinItemRequest(data), 0);
- }
if (info == null) {
// Legacy shortcuts are only supported for primary profile.
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index e3fe87d..782a869 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -109,15 +109,11 @@
mInstallSessionTracker = InstallSessionHelper.INSTANCE.get(context)
.registerInstallTracker(mModel, MODEL_EXECUTOR);
- if (!mContext.getResources().getBoolean(R.bool.notification_dots_enabled)) {
- mNotificationDotsObserver = null;
- } else {
- // Register an observer to rebind the notification listener when dots are re-enabled.
- mNotificationDotsObserver =
- newNotificationSettingsObserver(mContext, this::onNotificationSettingsChanged);
- mNotificationDotsObserver.register();
- mNotificationDotsObserver.dispatchOnChange();
- }
+ // Register an observer to rebind the notification listener when dots are re-enabled.
+ mNotificationDotsObserver =
+ newNotificationSettingsObserver(mContext, this::onNotificationSettingsChanged);
+ mNotificationDotsObserver.register();
+ mNotificationDotsObserver.dispatchOnChange();
}
public LauncherAppState(Context context, @Nullable String iconCacheFileName) {
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index e8b5568..fdbbf4e 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -872,7 +872,6 @@
* Removes widgets which are registered to the Launcher's host, but are not present
* in our model.
*/
- @TargetApi(Build.VERSION_CODES.O)
public void removeGhostWidgets(SQLiteDatabase db) {
// Get all existing widget ids.
final AppWidgetHost host = newLauncherWidgetHost();
diff --git a/src/com/android/launcher3/MainProcessInitializer.java b/src/com/android/launcher3/MainProcessInitializer.java
index 5f6ecb5..f2a3de7 100644
--- a/src/com/android/launcher3/MainProcessInitializer.java
+++ b/src/com/android/launcher3/MainProcessInitializer.java
@@ -38,7 +38,6 @@
protected void init(Context context) {
FileLog.setDir(context.getApplicationContext().getFilesDir());
FeatureFlags.initialize(context);
- SessionCommitReceiver.applyDefaultUserPrefs(context);
IconShape.init(context);
if (BitmapCreationCheck.ENABLED) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index e13d89f..4303dee 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -195,9 +195,7 @@
mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * density);
mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * density);
- if (Utilities.ATLEAST_OREO) {
- setDefaultFocusHighlightEnabled(false);
- }
+ setDefaultFocusHighlightEnabled(false);
}
protected void setDefaultInterpolator(Interpolator interpolator) {
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 89f0a3d..a8d6490 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -16,55 +16,32 @@
package com.android.launcher3;
-import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle;
-
-import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
import android.os.UserHandle;
-import android.provider.Settings;
import android.text.TextUtils;
-import android.util.Log;
import com.android.launcher3.pm.InstallSessionHelper;
-import com.android.launcher3.util.Executors;
import java.util.List;
/**
* BroadcastReceiver to handle session commit intent.
*/
-@TargetApi(Build.VERSION_CODES.O)
public class SessionCommitReceiver extends BroadcastReceiver {
- private static final String TAG = "SessionCommitReceiver";
-
- // The content provider for the add to home screen setting. It should be of the format:
- // <package name>.addtohomescreen
- private static final String MARKER_PROVIDER_PREFIX = ".addtohomescreen";
-
// Preference key for automatically adding icon to homescreen.
public static final String ADD_ICON_PREFERENCE_KEY = "pref_add_icon_to_home";
- public static final String ADD_ICON_PREFERENCE_INITIALIZED_KEY =
- "pref_add_icon_to_home_initialized";
@Override
public void onReceive(Context context, Intent intent) {
- if (!isEnabled(context) || !Utilities.ATLEAST_OREO) {
+ if (!isEnabled(context)) {
// User has decided to not add icons on homescreen.
return;
}
@@ -89,16 +66,6 @@
queueAppIconAddition(context, info.getAppPackageName(), user);
}
- public static void queuePromiseAppIconAddition(Context context, SessionInfo sessionInfo) {
- String packageName = sessionInfo.getAppPackageName();
- if (context.getSystemService(LauncherApps.class)
- .getActivityList(packageName, getUserHandle(sessionInfo)).isEmpty()) {
- // Ensure application isn't already installed.
- queueAppIconAddition(context, packageName, sessionInfo.getAppLabel(),
- sessionInfo.getAppIcon(), getUserHandle(sessionInfo));
- }
- }
-
public static void queueAppIconAddition(Context context, String packageName, UserHandle user) {
List<LauncherActivityInfo> activities = context.getSystemService(LauncherApps.class)
.getActivityList(packageName, user);
@@ -106,85 +73,11 @@
// no activity found
return;
}
- queueAppIconAddition(context, packageName, activities.get(0).getLabel(), null, user);
- }
- private static void queueAppIconAddition(Context context, String packageName,
- CharSequence label, Bitmap icon, UserHandle user) {
- Intent data = new Intent();
- data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent().setComponent(
- new ComponentName(packageName, "")).setPackage(packageName));
- data.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
- data.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
-
- InstallShortcutReceiver.queueApplication(data, user, context);
+ InstallShortcutReceiver.queueApplication(activities.get(0), context);
}
public static boolean isEnabled(Context context) {
return Utilities.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true);
}
-
- public static void applyDefaultUserPrefs(final Context context) {
- if (!Utilities.ATLEAST_OREO) {
- return;
- }
- SharedPreferences prefs = Utilities.getPrefs(context);
- if (prefs.getAll().isEmpty()) {
- // This logic assumes that the code is the first thing that is executed (before any
- // shared preference is written).
- // TODO: Move this logic to DB upgrade once we have proper support for db downgrade
- // If it is a fresh start, just apply the default value. We use prefs.isEmpty() to infer
- // a fresh start as put preferences always contain some values corresponding to current
- // grid.
- prefs.edit().putBoolean(ADD_ICON_PREFERENCE_KEY, true).apply();
- } else if (!prefs.contains(ADD_ICON_PREFERENCE_INITIALIZED_KEY)) {
- new PrefInitTask(context).executeOnExecutor(Executors.THREAD_POOL_EXECUTOR);
- }
- }
-
- private static class PrefInitTask extends AsyncTask<Void, Void, Void> {
- private final Context mContext;
-
- PrefInitTask(Context context) {
- mContext = context;
- }
-
- @Override
- protected Void doInBackground(Void... voids) {
- boolean addIconToHomeScreenEnabled = readValueFromMarketApp();
- Utilities.getPrefs(mContext).edit()
- .putBoolean(ADD_ICON_PREFERENCE_KEY, addIconToHomeScreenEnabled)
- .putBoolean(ADD_ICON_PREFERENCE_INITIALIZED_KEY, true)
- .apply();
- return null;
- }
-
- public boolean readValueFromMarketApp() {
- // Get the marget package
- ResolveInfo ri = mContext.getPackageManager().resolveActivity(
- new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET),
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_SYSTEM_ONLY);
- if (ri == null) {
- return true;
- }
-
- Cursor c = null;
- try {
- c = mContext.getContentResolver().query(
- Uri.parse("content://" + ri.activityInfo.packageName
- + MARKER_PROVIDER_PREFIX),
- null, null, null, null);
- if (c.moveToNext()) {
- return c.getInt(c.getColumnIndexOrThrow(Settings.NameValueTable.VALUE)) != 0;
- }
- } catch (Exception e) {
- Log.d(TAG, "Error reading add to homescreen preference", e);
- } finally {
- if (c != null) {
- c.close();
- }
- }
- return true;
- }
- }
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index bf63788..068d0bc 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ICON_BADGED;
-import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.Person;
@@ -48,7 +47,6 @@
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Message;
-import android.os.PowerManager;
import android.os.TransactionTooLargeException;
import android.provider.Settings;
import android.text.Spannable;
@@ -65,7 +63,6 @@
import androidx.core.os.BuildCompat;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.graphics.GridOptionsProvider;
import com.android.launcher3.graphics.TintedDrawableSpan;
@@ -113,12 +110,6 @@
public static final boolean ATLEAST_P =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
- public static final boolean ATLEAST_OREO_MR1 =
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1;
-
- public static final boolean ATLEAST_OREO =
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
-
/**
* Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
*/
@@ -494,21 +485,6 @@
LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE);
}
- /**
- * @return {@link SharedPreferences} that backs {@link FeatureFlags}
- */
- public static SharedPreferences getFeatureFlagsPrefs(Context context) {
- // Use application context for shared preferences, so that we use a single cached instance
- return context.getApplicationContext().getSharedPreferences(
- FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE);
- }
-
- public static boolean areAnimationsEnabled(Context context) {
- return ATLEAST_OREO
- ? ValueAnimator.areAnimatorsEnabled()
- : !context.getSystemService(PowerManager.class).isPowerSaveMode();
- }
-
public static boolean isWallpaperAllowed(Context context) {
return context.getSystemService(WallpaperManager.class).isSetWallpaperAllowed();
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 77b8a32..2d711e6 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -55,6 +55,7 @@
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusedItemDecorator;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -486,7 +487,7 @@
if (mWorkModeSwitch != null) {
mWorkModeSwitch.setWorkTabVisible(pos == AdapterHolder.WORK
&& mAllAppsStore.hasModelFlag(
- FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
+ FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
}
}
@@ -538,6 +539,10 @@
int padding = mHeader.getMaxTranslation();
for (int i = 0; i < mAH.length; i++) {
mAH[i].padding.top = padding;
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mUsingTabs) {
+ //add extra space between tabs and recycler view
+ mAH[i].padding.top += mLauncher.getDeviceProfile().edgeMarginPx;
+ }
mAH[i].applyPadding();
}
}
@@ -652,6 +657,9 @@
applyVerticalFadingEdgeEnabled(verticalFadingEdge);
applyPadding();
setupOverlay();
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ recyclerView.addItemDecoration(new AllAppsSectionDecorator(getApps()));
+ }
}
void setupOverlay() {
diff --git a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
new file mode 100644
index 0000000..ac55072
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.search.SearchSectionInfo;
+import com.android.launcher3.util.Themes;
+
+import java.util.List;
+
+/**
+ * ItemDecoration class that groups items in {@link AllAppsRecyclerView}
+ */
+public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
+
+ private final AlphabeticalAppsList mApps;
+
+ AllAppsSectionDecorator(AlphabeticalAppsList appsList) {
+ mApps = appsList;
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ // Iterate through views in recylerview and draw bounds around views in the same section.
+ // Since views in the same section will follow each other, we can skip to a last view in
+ // a section to get the bounds of the section without having to iterate on evert item.
+ int itemCount = parent.getChildCount();
+ List<AlphabeticalAppsList.AdapterItem> adapterItems = mApps.getAdapterItems();
+ SectionDecorationHandler lastDecorationHandler = null;
+ int i = 0;
+ while (i < itemCount) {
+ View view = parent.getChildAt(i);
+ int position = parent.getChildAdapterPosition(view);
+ AlphabeticalAppsList.AdapterItem adapterItem = adapterItems.get(position);
+ if (adapterItem.searchSectionInfo != null) {
+ SearchSectionInfo sectionInfo = adapterItem.searchSectionInfo;
+ int endIndex = Math.min(i + sectionInfo.getPosEnd() - position, itemCount - 1);
+ SectionDecorationHandler decorationHandler = sectionInfo.getDecorationHandler();
+ if (decorationHandler != lastDecorationHandler && lastDecorationHandler != null) {
+ drawDecoration(c, lastDecorationHandler, parent);
+ }
+ lastDecorationHandler = decorationHandler;
+ if (decorationHandler != null) {
+ decorationHandler.extendBounds(view);
+ }
+
+ if (endIndex > i) {
+ i = endIndex;
+ continue;
+ }
+
+ }
+ i++;
+ }
+ if (lastDecorationHandler != null) {
+ drawDecoration(c, lastDecorationHandler, parent);
+ }
+ }
+
+ private void drawDecoration(Canvas c, SectionDecorationHandler decorationHandler, View parent) {
+ if (decorationHandler == null) return;
+ if (decorationHandler.mIsFullWidth) {
+ decorationHandler.mBounds.left = parent.getPaddingLeft();
+ decorationHandler.mBounds.right = parent.getWidth() - parent.getPaddingRight();
+ }
+ decorationHandler.onDraw(c);
+ decorationHandler.reset();
+ }
+
+ /**
+ * Handles grouping and drawing of items in the same all apps sections.
+ */
+ public static class SectionDecorationHandler {
+ protected RectF mBounds = new RectF();
+ private final boolean mIsFullWidth;
+ private final float mRadius;
+ private final int mFillcolor;
+ Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+
+ public SectionDecorationHandler(Context context, boolean isFullWidth) {
+ mIsFullWidth = isFullWidth;
+ mFillcolor = context.getColor(R.color.all_apps_section_fill);
+ mRadius = Themes.getDialogCornerRadius(context);
+ }
+
+ /**
+ * Extends current bounds to include view
+ */
+ public void extendBounds(View view) {
+ if (mBounds.isEmpty()) {
+ mBounds.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+ } else {
+ mBounds.set(
+ Math.min(mBounds.left, view.getLeft()),
+ Math.min(mBounds.top, view.getTop()),
+ Math.max(mBounds.right, view.getRight()),
+ Math.max(mBounds.bottom, view.getBottom())
+ );
+ }
+ }
+
+ /**
+ * Draw bounds onto canvas
+ */
+ public void onDraw(Canvas canvas) {
+ mPaint.setColor(mFillcolor);
+ canvas.drawRoundRect(mBounds, mRadius, mRadius, mPaint);
+ }
+
+ /**
+ * Reset view bounds to empty
+ */
+ public void reset() {
+ mBounds.setEmpty();
+ }
+ }
+
+}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 266bfa2..0fc04a7 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -31,7 +31,6 @@
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
-import java.util.stream.Collectors;
/**
* The alphabetically sorted list of applications.
@@ -129,6 +128,10 @@
item.searchSectionInfo = sectionInfo;
return item;
}
+
+ boolean isCountedForAccessibility() {
+ return viewType == AllAppsGridAdapter.VIEW_TYPE_ICON;
+ }
}
private final BaseDraggingActivity mLauncher;
@@ -137,8 +140,8 @@
private final List<AppInfo> mApps = new ArrayList<>();
private final AllAppsStore mAllAppsStore;
- // The set of filtered apps with the current filter
- private final List<AppInfo> mFilteredApps = new ArrayList<>();
+ // The number of results in current adapter
+ private int mAccessibilityResultsCount = 0;
// The current set of adapter items
private final ArrayList<AdapterItem> mAdapterItems = new ArrayList<>();
// The set of sections that we allow fast-scrolling to (includes non-merged sections)
@@ -207,7 +210,7 @@
* Returns the number of applications in this list.
*/
public int getNumFilteredApps() {
- return mFilteredApps.size();
+ return mAccessibilityResultsCount;
}
/**
@@ -221,7 +224,7 @@
* Returns whether there are no filtered results.
*/
public boolean hasNoFilteredResults() {
- return (mSearchResults != null) && mFilteredApps.isEmpty();
+ return (mSearchResults != null) && mAccessibilityResultsCount == 0;
}
/**
@@ -307,13 +310,20 @@
int appIndex = 0;
// Prepare to update the list of sections, filtered apps, etc.
- mFilteredApps.clear();
+ mAccessibilityResultsCount = 0;
mFastScrollerSections.clear();
mAdapterItems.clear();
+ SearchSectionInfo appSection = new SearchSectionInfo();
+ appSection.setDecorationHandler(
+ new AllAppsSectionDecorator.SectionDecorationHandler(mLauncher, true));
+
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
// ordered set of sections
+
if (!hasFilter()) {
+ mAccessibilityResultsCount = mApps.size();
+ appSection.setPosStart(position);
for (AppInfo info : mApps) {
String sectionName = info.sectionName;
@@ -329,15 +339,33 @@
if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
lastFastScrollerSectionInfo.fastScrollToItem = appItem;
}
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ appItem.searchSectionInfo = appSection;
+ }
mAdapterItems.add(appItem);
- mFilteredApps.add(info);
}
+ appSection.setPosEnd(mApps.isEmpty() ? appSection.getPosStart() : position - 1);
} else {
- mAdapterItems.addAll(mSearchResults);
- List<AppInfo> appInfos = mSearchResults.stream().filter(
- i -> AllAppsGridAdapter.isIconViewType(i.viewType)).map(i -> i.appInfo).collect(
- Collectors.toList());
- mFilteredApps.addAll(appInfos);
+ List<AppInfo> appInfos = new ArrayList<>();
+ SearchSectionInfo lastSection = null;
+ for (int i = 0; i < mSearchResults.size(); i++) {
+ AdapterItem adapterItem = mSearchResults.get(i);
+ adapterItem.position = i;
+ mAdapterItems.add(adapterItem);
+ if (adapterItem.searchSectionInfo != lastSection) {
+ adapterItem.searchSectionInfo.setPosStart(i);
+ if (lastSection != null) {
+ lastSection.setPosEnd(i - 1);
+ }
+ lastSection = adapterItem.searchSectionInfo;
+ }
+ if (AllAppsGridAdapter.isIconViewType(adapterItem.viewType)) {
+ appInfos.add(adapterItem.appInfo);
+ }
+ if (adapterItem.isCountedForAccessibility()) {
+ mAccessibilityResultsCount++;
+ }
+ }
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
// Append the search market item
if (hasNoFilteredResults()) {
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
index 5beb956..fb78651 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
@@ -19,6 +19,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHandler;
import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
@@ -36,12 +37,21 @@
private static final int MAX_RESULTS_COUNT = 5;
- private final SearchSectionInfo mSearchSectionInfo;
+ private static final int SECTION_TYPE_HEADER = 0;
+ private static final int SECTION_TYPE_APPS = 1;
+
+ private final SearchSectionInfo[] mSearchSectionInfos;
private final LauncherAppState mLauncherAppState;
+
public AppsSearchPipeline(LauncherAppState launcherAppState) {
mLauncherAppState = launcherAppState;
- mSearchSectionInfo = new SearchSectionInfo(R.string.search_corpus_apps);
+ mSearchSectionInfos = new SearchSectionInfo[]{
+ new SearchSectionInfo(R.string.search_corpus_apps),
+ new SearchSectionInfo()
+ };
+ mSearchSectionInfos[SECTION_TYPE_APPS].setDecorationHandler(
+ new SectionDecorationHandler(launcherAppState.getContext(), true));
}
@Override
@@ -78,12 +88,12 @@
if (matchingApps.isEmpty()) {
return items;
}
- items.add(AdapterItem.asSearchTitle(mSearchSectionInfo, 0));
+ items.add(AdapterItem.asSearchTitle(mSearchSectionInfos[SECTION_TYPE_HEADER], 0));
int existingItems = items.size();
int searchResultsCount = Math.min(matchingApps.size(), MAX_RESULTS_COUNT);
for (int i = 0; i < searchResultsCount; i++) {
AdapterItem appItem = AdapterItem.asApp(i + existingItems, "", matchingApps.get(i), i);
- appItem.searchSectionInfo = mSearchSectionInfo;
+ appItem.searchSectionInfo = mSearchSectionInfos[SECTION_TYPE_APPS];
items.add(appItem);
}
diff --git a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
index 880b246..dee0ffd 100644
--- a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
+++ b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
@@ -17,20 +17,59 @@
import android.content.Context;
+import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHandler;
+
/**
* Info class for a search section
*/
public class SearchSectionInfo {
+
private final int mTitleResId;
+ private SectionDecorationHandler mDecorationHandler;
+
+ public int getPosStart() {
+ return mPosStart;
+ }
+
+ public void setPosStart(int posStart) {
+ mPosStart = posStart;
+ }
+
+ public int getPosEnd() {
+ return mPosEnd;
+ }
+
+ public void setPosEnd(int posEnd) {
+ mPosEnd = posEnd;
+ }
+
+ private int mPosStart;
+ private int mPosEnd;
+
+ public SearchSectionInfo() {
+ this(-1);
+ }
public SearchSectionInfo(int titleResId) {
mTitleResId = titleResId;
}
+ public void setDecorationHandler(SectionDecorationHandler sectionDecorationHandler) {
+ mDecorationHandler = sectionDecorationHandler;
+ }
+
+
+ public SectionDecorationHandler getDecorationHandler() {
+ return mDecorationHandler;
+ }
+
/**
* Returns the section's title
*/
public String getTitle(Context context) {
+ if (mTitleResId == -1) {
+ return "";
+ }
return context.getString(mTitleResId);
}
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 860cceb..6ad43ea 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -198,6 +198,7 @@
public OvershootParams(float startProgress, float overshootPastProgress,
float endProgress, float velocityPxPerMs, int totalDistancePx, Context context) {
velocityPxPerMs = Math.abs(velocityPxPerMs);
+ overshootPastProgress = Math.max(overshootPastProgress, startProgress);
start = startProgress;
int startPx = (int) (start * totalDistancePx);
// Overshoot by about half a frame.
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 4195933..5362575 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -149,7 +149,7 @@
mProgressAnimator = null;
}
if (mAnimHolders.isEmpty()) {
- // Add a dummy animation to that the duration is respected
+ // Add a placeholder animation to that the duration is respected
add(ValueAnimator.ofFloat(0, 1).setDuration(mDuration));
}
return mAnim;
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 03028d3..ef666f0 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -463,10 +463,10 @@
}
public void forceTouchMove() {
- int[] dummyCoordinates = mCoordinatesTemp;
- DropTarget dropTarget = findDropTarget(mLastTouch.x, mLastTouch.y, dummyCoordinates);
- mDragObject.x = dummyCoordinates[0];
- mDragObject.y = dummyCoordinates[1];
+ int[] placeholderCoordinates = mCoordinatesTemp;
+ DropTarget dropTarget = findDropTarget(mLastTouch.x, mLastTouch.y, placeholderCoordinates);
+ mDragObject.x = placeholderCoordinates[0];
+ mDragObject.y = placeholderCoordinates[1];
checkTouchMove(dropTarget);
}
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index de0fa1a..86b93d0 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -187,9 +187,6 @@
*/
@TargetApi(Build.VERSION_CODES.O)
public void setItemInfo(final ItemInfo info) {
- if (!Utilities.ATLEAST_OREO) {
- return;
- }
if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
info.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
info.itemType != LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 9982b39..f543e47 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -49,14 +49,14 @@
// Class name used in the target component, such that it will never represent an
// actual existing class.
- private static final String DUMMY_COMPONENT_CLASS = "pinned-shortcut";
+ private static final String STUB_COMPONENT_CLASS = "pinned-shortcut";
private final PinItemRequest mRequest;
private final ShortcutInfo mInfo;
private final Context mContext;
public PinShortcutRequestActivityInfo(PinItemRequest request, Context context) {
- super(new ComponentName(request.getShortcutInfo().getPackage(), DUMMY_COMPONENT_CLASS),
+ super(new ComponentName(request.getShortcutInfo().getPackage(), STUB_COMPONENT_CLASS),
request.getShortcutInfo().getUserHandle());
mRequest = request;
mInfo = request.getShortcutInfo();
diff --git a/src/com/android/launcher3/graphics/IconShape.java b/src/com/android/launcher3/graphics/IconShape.java
index 4369385..b208a40 100644
--- a/src/com/android/launcher3/graphics/IconShape.java
+++ b/src/com/android/launcher3/graphics/IconShape.java
@@ -43,8 +43,9 @@
import android.view.View;
import android.view.ViewOutlineProvider;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;
@@ -59,8 +60,6 @@
import java.util.ArrayList;
import java.util.List;
-import androidx.annotation.Nullable;
-
/**
* Abstract representation of the shape of an icon shape
*/
@@ -381,9 +380,6 @@
* Initializes the shape which is closest to the {@link AdaptiveIconDrawable}
*/
public static void init(Context context) {
- if (!Utilities.ATLEAST_OREO) {
- return;
- }
pickBestShape(context);
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index de72534..0374009 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -37,7 +37,7 @@
*
* <pre>
* All of the event ids are defined here.
- * Most of the methods are dummy methods for Launcher3
+ * Most of the methods are placeholder methods for Launcher3
* Actual call happens only for Launcher variant that implements QuickStep.
* </pre>
*/
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index e094cab..31a81b8 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -147,7 +147,7 @@
}
/**
- * Dummy method.
+ * Placeholder method.
*/
public void logActionTip(int actionType, int viewType) {
}
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 6158a9c..fd8520d 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -422,7 +422,7 @@
@Override
public FixedContainerItems clone() {
- return new FixedContainerItems(containerId, Collections.unmodifiableList(items));
+ return new FixedContainerItems(containerId, new ArrayList<>(items));
}
}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index dca4ec0..c0ae6f9 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -24,7 +24,6 @@
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -32,8 +31,6 @@
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.SessionCommitReceiver;
-import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.IconCache;
@@ -108,11 +105,6 @@
appsList.removePackage(packages[i], mUser);
}
appsList.addPackage(context, packages[i], mUser);
-
- // Automatically add homescreen icon for work profile apps for below O device.
- if (!Utilities.ATLEAST_OREO && !Process.myUserHandle().equals(mUser)) {
- SessionCommitReceiver.queueAppIconAddition(context, packages[i], mUser);
- }
}
flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
@@ -331,7 +323,7 @@
InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser);
}
- if (Utilities.ATLEAST_OREO && mOp == OP_ADD) {
+ if (mOp == OP_ADD) {
// Load widgets for the new package. Changes due to app updates are handled through
// AppWidgetHost events, this is just to initialize the long-press options.
for (int i = 0; i < N; i++) {
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index b17b062..aee1f2a 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -138,8 +138,7 @@
info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
- if (Utilities.ATLEAST_OREO
- && appInfo.targetSdkVersion >= Build.VERSION_CODES.O
+ if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O
&& Process.myUserHandle().equals(lai.getUser())) {
// The icon for a non-primary user is badged, hence it's not exactly an adaptive icon.
info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index a7bf1f3..1e1d093 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -216,7 +216,7 @@
if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT || hasStatusFlag(
FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON))) {
// Legacy shortcuts and promise icons with web UI may not have a componentName but just
- // a packageName. In that case create a dummy componentName instead of adding additional
+ // a packageName. In that case create a empty componentName instead of adding additional
// check everywhere.
String pkg = intent.getPackage();
return pkg == null ? null : new ComponentName(pkg, IconCache.EMPTY_CLASS_NAME);
diff --git a/src/com/android/launcher3/notification/NotificationKeyData.java b/src/com/android/launcher3/notification/NotificationKeyData.java
index a1917ec..1dda3df 100644
--- a/src/com/android/launcher3/notification/NotificationKeyData.java
+++ b/src/com/android/launcher3/notification/NotificationKeyData.java
@@ -30,9 +30,9 @@
/**
* The key data associated with the notification, used to determine what to include
- * in dots and dummy popup views before they are populated.
+ * in dots and stub popup views before they are populated.
*
- * @see NotificationInfo for the full data used when populating the dummy views.
+ * @see NotificationInfo for the full data used when populating the stub views.
*/
public class NotificationKeyData {
public final String notificationKey;
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index b03aa9c..32f060b 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -137,7 +137,7 @@
setOnClickListener(mNotificationInfo);
}
setContentTranslation(0);
- // Add a dummy ItemInfo so that logging populates the correct container and item types
+ // Add a stub ItemInfo so that logging populates the correct container and item types
// instead of DEFAULT_CONTAINERTYPE and DEFAULT_ITEMTYPE, respectively.
setTag(NOTIFICATION_ITEM_INFO);
if (animate) {
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 901d27f..ce4644f 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -18,7 +18,9 @@
import static com.android.launcher3.Utilities.getPrefs;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller;
@@ -32,6 +34,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
+import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.Utilities;
@@ -167,7 +170,7 @@
* Attempt to restore workspace layout if the session is triggered due to device restore.
*/
public boolean restoreDbIfApplicable(@NonNull final SessionInfo info) {
- if (!Utilities.ATLEAST_OREO || !FeatureFlags.ENABLE_DATABASE_RESTORE.get()) {
+ if (!FeatureFlags.ENABLE_DATABASE_RESTORE.get()) {
return false;
}
if (isRestore(info)) {
@@ -203,7 +206,7 @@
* - A promise icon for the session has not already been created
*/
void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) {
- if (Utilities.ATLEAST_OREO && FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
+ if (FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
&& SessionCommitReceiver.isEnabled(mAppContext)
&& verify(sessionInfo) != null
&& sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER
@@ -212,7 +215,21 @@
&& !mPromiseIconIds.contains(sessionInfo.getSessionId())
&& new PackageManagerHelper(mAppContext).getApplicationInfo(
sessionInfo.getAppPackageName(), getUserHandle(sessionInfo), 0) == null) {
- SessionCommitReceiver.queuePromiseAppIconAddition(mAppContext, sessionInfo);
+
+ String packageName = sessionInfo.getAppPackageName();
+ if (mAppContext.getSystemService(LauncherApps.class)
+ .getActivityList(packageName, getUserHandle(sessionInfo)).isEmpty()) {
+ // Ensure application isn't already installed.
+ Intent data = new Intent();
+ data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent().setComponent(
+ new ComponentName(packageName, "")).setPackage(packageName));
+ data.putExtra(Intent.EXTRA_SHORTCUT_NAME, sessionInfo.getAppLabel());
+ data.putExtra(Intent.EXTRA_SHORTCUT_ICON, sessionInfo.getAppIcon());
+
+ InstallShortcutReceiver.queueApplication(data, getUserHandle(sessionInfo),
+ mAppContext);
+ }
+
mPromiseIconIds.add(sessionInfo.getSessionId());
updatePromiseIconPrefs();
}
diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
index 40d7031..7af14c6 100644
--- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
@@ -27,7 +27,6 @@
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Process;
@@ -39,13 +38,13 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -175,37 +174,23 @@
List<ShortcutConfigActivityInfo> result = new ArrayList<>();
UserHandle myUser = Process.myUserHandle();
- if (Utilities.ATLEAST_OREO) {
- final List<UserHandle> users;
- final String packageName;
- if (packageUser == null) {
- users = UserCache.INSTANCE.get(context).getUserProfiles();
- packageName = null;
- } else {
- users = new ArrayList<>(1);
- users.add(packageUser.mUser);
- packageName = packageUser.mPackageName;
- }
- LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
- for (UserHandle user : users) {
- boolean ignoreTargetSdk = myUser.equals(user);
- for (LauncherActivityInfo activityInfo :
- launcherApps.getShortcutConfigActivityList(packageName, user)) {
- if (ignoreTargetSdk || activityInfo.getApplicationInfo().targetSdkVersion
- >= Build.VERSION_CODES.O) {
- result.add(new ShortcutConfigActivityInfoVO(activityInfo));
- }
- }
- }
+ final List<UserHandle> users;
+ final String packageName;
+ if (packageUser == null) {
+ users = UserCache.INSTANCE.get(context).getUserProfiles();
+ packageName = null;
} else {
- if (packageUser == null || packageUser.mUser.equals(myUser)) {
- Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
- if (packageUser != null) {
- intent.setPackage(packageUser.mPackageName);
- }
- for (ResolveInfo info :
- context.getPackageManager().queryIntentActivities(intent, 0)) {
- result.add(new ShortcutConfigActivityInfoVL(info.activityInfo));
+ users = Collections.singletonList(packageUser.mUser);
+ packageName = packageUser.mPackageName;
+ }
+ LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
+ for (UserHandle user : users) {
+ boolean ignoreTargetSdk = myUser.equals(user);
+ for (LauncherActivityInfo activityInfo :
+ launcherApps.getShortcutConfigActivityList(packageName, user)) {
+ if (ignoreTargetSdk || activityInfo.getApplicationInfo().targetSdkVersion
+ >= Build.VERSION_CODES.O) {
+ result.add(new ShortcutConfigActivityInfoVO(activityInfo));
}
}
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 614cf14..896fb18 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -52,7 +52,6 @@
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
import com.android.launcher3.dot.DotInfo;
@@ -400,9 +399,7 @@
} else if (view instanceof ImageView) {
// Only the system shortcut icon shows on a gray background header.
info.setIconAndContentDescriptionFor((ImageView) view);
- if (Utilities.ATLEAST_OREO) {
- view.setTooltipText(view.getContentDescription());
- }
+ view.setTooltipText(view.getContentDescription());
}
view.setTag(info);
view.setOnClickListener(info);
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index d3213a1..ec3a467 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -18,7 +18,6 @@
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
-import static com.android.launcher3.SessionCommitReceiver.ADD_ICON_PREFERENCE_KEY;
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
import static com.android.launcher3.states.RotationHelper.getAllowRotationDefaultValue;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
@@ -172,11 +171,6 @@
protected boolean initPreference(Preference preference) {
switch (preference.getKey()) {
case NOTIFICATION_DOTS_PREFERENCE_KEY:
- if (!Utilities.ATLEAST_OREO ||
- !getResources().getBoolean(R.bool.notification_dots_enabled)) {
- return false;
- }
-
// Listen to system notification dot settings while this UI is active.
mNotificationDotsObserver = newNotificationSettingsObserver(
getActivity(), (NotificationDotsPreference) preference);
@@ -188,9 +182,6 @@
mNotificationDotsObserver.dispatchOnChange();
return true;
- case ADD_ICON_PREFERENCE_KEY:
- return Utilities.ATLEAST_OREO;
-
case ALLOW_ROTATION_PREFERENCE_KEY:
if (getResources().getBoolean(R.bool.allow_rotation)) {
// Launcher supports rotation by default. No need to show this setting.
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 60b87d9..6ff1254 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -16,6 +16,8 @@
package com.android.launcher3.statemanager;
+import static android.animation.ValueAnimator.areAnimatorsEnabled;
+
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
import android.animation.Animator;
@@ -26,7 +28,6 @@
import android.os.Looper;
import android.util.Log;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
@@ -179,7 +180,7 @@
private void goToState(STATE_TYPE state, boolean animated, long delay,
final Runnable onCompleteRunnable) {
- animated &= Utilities.areAnimationsEnabled(mActivity);
+ animated &= areAnimatorsEnabled();
if (mActivity.isInState(state)) {
if (mConfig.currentAnimation == null) {
// Run any queued runnable
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 9816f13..8616881 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -99,6 +99,7 @@
public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
public static final String REQUEST_OVERVIEW_ACTIONS_ENABLED = "overview-actions-enabled";
+ public static final String REQUEST_OVERVIEW_SHARE_ENABLED = "overview-share-enabled";
public static boolean sDisableSensorRotation;
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 66dbf6a..02ca926 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -513,15 +513,7 @@
if (mAtomicAnim == null) {
return 0;
}
- if (Utilities.ATLEAST_OREO) {
- return mAtomicAnim.getTotalDuration() - mAtomicAnim.getCurrentPlayTime();
- } else {
- long remainingDuration = 0;
- for (Animator anim : mAtomicAnim.getChildAnimations()) {
- remainingDuration = Math.max(remainingDuration, anim.getDuration());
- }
- return remainingDuration;
- }
+ return mAtomicAnim.getTotalDuration() - mAtomicAnim.getCurrentPlayTime();
}
protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 86f3431..523545a 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -37,7 +37,6 @@
import android.os.Build;
import android.os.Bundle;
import android.os.PatternMatcher;
-import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
@@ -46,7 +45,6 @@
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -96,36 +94,12 @@
* Returns the application info for the provided package or null
*/
public ApplicationInfo getApplicationInfo(String packageName, UserHandle user, int flags) {
- if (Utilities.ATLEAST_OREO) {
- try {
- ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
- return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 || !info.enabled
- ? null : info;
- } catch (PackageManager.NameNotFoundException e) {
- return null;
- }
- } else {
- final boolean isPrimaryUser = Process.myUserHandle().equals(user);
- if (!isPrimaryUser && (flags == 0)) {
- // We are looking for an installed app on a secondary profile. Prior to O, the only
- // entry point for work profiles is through the LauncherActivity.
- List<LauncherActivityInfo> activityList =
- mLauncherApps.getActivityList(packageName, user);
- return activityList.size() > 0 ? activityList.get(0).getApplicationInfo() : null;
- }
- try {
- ApplicationInfo info = mPm.getApplicationInfo(packageName, flags);
- // There is no way to check if the app is installed for managed profile. But for
- // primary profile, we can still have this check.
- if (isPrimaryUser && ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0)
- || !info.enabled) {
- return null;
- }
- return info;
- } catch (PackageManager.NameNotFoundException e) {
- // Package not found
- return null;
- }
+ try {
+ ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
+ return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 || !info.enabled
+ ? null : info;
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
}
}
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index 3e48006..50166c3 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -19,8 +19,6 @@
import android.view.View;
import android.view.Window;
-import com.android.launcher3.Utilities;
-
import java.util.Arrays;
/**
@@ -78,12 +76,10 @@
}
private int getSysUiVisibilityFlags(int stateFlag, int currentVisibility) {
- if (Utilities.ATLEAST_OREO) {
- if ((stateFlag & FLAG_LIGHT_NAV) != 0) {
- currentVisibility |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
- } else if ((stateFlag & FLAG_DARK_NAV) != 0) {
- currentVisibility &= ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
- }
+ if ((stateFlag & FLAG_LIGHT_NAV) != 0) {
+ currentVisibility |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ } else if ((stateFlag & FLAG_DARK_NAV) != 0) {
+ currentVisibility &= ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
}
if ((stateFlag & FLAG_LIGHT_STATUS) != 0) {
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 8186dfa..52a82f8 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -256,7 +256,6 @@
Drawable drawable = null;
Drawable badge = null;
boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get()
- && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& !info.isDisabled(); // Use original icon for disabled icons.
Drawable btvIcon = originalView instanceof BubbleTextView
? ((BubbleTextView) originalView).getIcon() : null;
@@ -383,8 +382,7 @@
@WorkerThread
@SuppressWarnings("WrongThread")
private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O
- || !(drawable instanceof AdaptiveIconDrawable)
+ if (!(drawable instanceof AdaptiveIconDrawable)
|| (drawable instanceof FolderAdaptiveIcon)) {
return 0;
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index e95dc5b..9ad2331 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -226,15 +226,15 @@
if (!TextUtils.isEmpty(pickerPackage)) {
intent.setPackage(pickerPackage);
}
- return launcher.startActivitySafely(v, intent, dummyInfo(intent));
+ return launcher.startActivitySafely(v, intent, placeholderInfo(intent));
}
- static WorkspaceItemInfo dummyInfo(Intent intent) {
- WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
- dummyInfo.intent = intent;
- dummyInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
- dummyInfo.container = LauncherSettings.Favorites.CONTAINER_SETTINGS;
- return dummyInfo;
+ static WorkspaceItemInfo placeholderInfo(Intent intent) {
+ WorkspaceItemInfo placeholderInfo = new WorkspaceItemInfo();
+ placeholderInfo.intent = intent;
+ placeholderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ placeholderInfo.container = LauncherSettings.Favorites.CONTAINER_SETTINGS;
+ return placeholderInfo;
}
public static class OptionItem {
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 6f2e179..780a1a1 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -80,9 +80,7 @@
setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
setBackgroundResource(R.drawable.widget_internal_focus_bg);
- if (Utilities.ATLEAST_OREO) {
- setExecutor(Executors.THREAD_POOL_EXECUTOR);
- }
+ setExecutor(Executors.THREAD_POOL_EXECUTOR);
if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
setOnLightBackground(true);
}
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index 4b6c569..c0c5c48 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -23,13 +23,11 @@
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
-import android.os.Process;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.Utilities;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.pm.UserCache;
@@ -84,22 +82,8 @@
return allWidgetsSteam(mContext).collect(Collectors.toList());
}
- if (Utilities.ATLEAST_OREO) {
- return mAppWidgetManager.getInstalledProvidersForPackage(
- packageUser.mPackageName, packageUser.mUser);
- }
-
- String pkg = packageUser.mPackageName;
- return Stream.concat(
- // Only get providers for the given package/user.
- mAppWidgetManager.getInstalledProvidersForProfile(packageUser.mUser)
- .stream()
- .filter(w -> w.provider.equals(pkg)),
- Process.myUserHandle().equals(packageUser.mUser)
- && mContext.getPackageName().equals(pkg)
- ? CustomWidgetManager.INSTANCE.get(mContext).stream()
- : Stream.empty())
- .collect(Collectors.toList());
+ return mAppWidgetManager.getInstalledProvidersForPackage(
+ packageUser.mPackageName, packageUser.mUser);
}
/**
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java
index 5a1f9ca..780a0f0 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/ColorExtractionAlgorithm.java
@@ -21,16 +21,16 @@
import android.util.Pair;
import android.util.Range;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.graphics.ColorUtils;
+
import com.android.launcher3.Utilities;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.graphics.ColorUtils;
-
/**
* Implementation of tonal color extraction
**/
@@ -69,7 +69,7 @@
// palettes. The best fit is tweaked to be closer to the source color
// and replaces the original palette
- // Get the most preeminent, non-blacklisted color.
+ // Get the most preeminent, non-disallowed color.
Integer bestColor = 0;
final float[] hsl = new float[3];
for (int i = 0; i < mainColorsSize; i++) {
@@ -78,7 +78,7 @@
Color.blue(colorValue), hsl);
// Stop when we find a color that meets our criteria
- if (!isBlacklisted(hsl)) {
+ if (!isDisallowed(hsl)) {
bestColor = colorValue;
break;
}
@@ -167,12 +167,12 @@
}
/**
- * Checks if a given color exists in the blacklist
+ * Checks if a given color exists in the disallowed_colors list.
* @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
* @return true if color should be avoided
*/
- private boolean isBlacklisted(float[] hsl) {
- for (ColorRange badRange: BLACKLISTED_COLORS) {
+ private boolean isDisallowed(float[] hsl) {
+ for (ColorRange badRange: DISALLOWED_COLORS) {
if (badRange.containsColor(hsl[0], hsl[1], hsl[2])) {
return true;
}
@@ -592,7 +592,7 @@
);
@SuppressWarnings("WeakerAccess")
- static final ColorRange[] BLACKLISTED_COLORS = new ColorRange[] {
+ static final ColorRange[] DISALLOWED_COLORS = new ColorRange[] {
// Red
new ColorRange(
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java
index 0fd0a35..9dbe47c 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompat.java
@@ -17,8 +17,7 @@
package com.android.launcher3.uioverrides.dynamicui;
import android.content.Context;
-
-import com.android.launcher3.Utilities;
+import android.os.Build;
import androidx.annotation.Nullable;
@@ -32,7 +31,7 @@
if (sInstance == null) {
context = context.getApplicationContext();
- if (Utilities.ATLEAST_OREO_MR1) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
try {
sInstance = new WallpaperManagerCompatVOMR1(context);
} catch (Throwable e) {
diff --git a/tests/src/com/android/launcher3/testcomponent/ListViewService.java b/tests/src/com/android/launcher3/testcomponent/ListViewService.java
index 3da20e0..9e3a492 100644
--- a/tests/src/com/android/launcher3/testcomponent/ListViewService.java
+++ b/tests/src/com/android/launcher3/testcomponent/ListViewService.java
@@ -89,7 +89,7 @@
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return SimpleViewsFactory.this;
}
- }.onBind(new Intent("dummy_intent"));
+ }.onBind(new Intent("stub_intent"));
}
}
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 201218b..5e42d9b 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -115,8 +115,7 @@
if (TestHelpers.isInLauncherProcess()) {
StrictMode.VmPolicy.Builder builder =
new StrictMode.VmPolicy.Builder()
-// b/154772063
-// .detectActivityLeaks()
+ .detectActivityLeaks()
.penaltyLog()
.penaltyListener(Runnable::run, violation -> {
if (sStrictmodeDetectedActivityLeak == null) {
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index 0e43d81..822fefc 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -30,7 +30,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -126,9 +125,6 @@
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
Intent... commandIntents) throws Throwable {
- if (!Utilities.ATLEAST_OREO) {
- return;
- }
clearHomescreen();
mDevice.pressHome();
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index e538f60..c9c846f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -16,8 +16,9 @@
package com.android.launcher3.tapl;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+
import static com.android.launcher3.tapl.OverviewTask.TASK_START_EVENT;
-import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import android.graphics.Point;
@@ -150,67 +151,68 @@
/**
* Swipes right or double presses the square button to switch to the previous app.
*/
+ @NonNull
public Background quickSwitchToPreviousApp() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to quick switch to the previous app")) {
verifyActiveContainer();
- quickSwitchToPreviousApp(getExpectedStateForQuickSwitch());
+ final boolean launcherWasVisible = mLauncher.isLauncherVisible();
+ boolean transposeInLandscape = false;
+ switch (mLauncher.getNavigationModel()) {
+ case TWO_BUTTON:
+ transposeInLandscape = true;
+ // Fall through, zero button and two button modes behave the same.
+ case ZERO_BUTTON: {
+ final int startX;
+ final int startY;
+ final int endX;
+ final int endY;
+ if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
+ // Swipe from the bottom left to the bottom right of the screen.
+ startX = 0;
+ startY = getSwipeStartY();
+ endX = mLauncher.getDevice().getDisplayWidth();
+ endY = startY;
+ } else {
+ // Swipe from the bottom right to the top right of the screen.
+ startX = getSwipeStartX();
+ startY = mLauncher.getRealDisplaySize().y - 1;
+ endX = startX;
+ endY = 0;
+ }
+ final boolean isZeroButton = mLauncher.getNavigationModel()
+ == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
+ LauncherInstrumentation.GestureScope gestureScope =
+ launcherWasVisible && isZeroButton
+ ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
+ : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
+ mLauncher.executeAndWaitForEvent(
+ () -> mLauncher.linearGesture(
+ startX, startY, endX, endY, 20, false, gestureScope),
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Quick switch gesture didn't change window state");
+ break;
+ }
+
+ case THREE_BUTTON:
+ // Double press the recents button.
+ UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps");
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL);
+ mLauncher.getOverview();
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.executeAndWaitForEvent(
+ () -> recentsButton.click(),
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Pressing recents button didn't change window state");
+ break;
+ }
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
return new Background(mLauncher);
}
}
- protected int getExpectedStateForQuickSwitch() {
- return BACKGROUND_APP_STATE_ORDINAL;
- }
-
- protected void quickSwitchToPreviousApp(int expectedState) {
- final boolean launcherWasVisible = mLauncher.isLauncherVisible();
- boolean transposeInLandscape = false;
- switch (mLauncher.getNavigationModel()) {
- case TWO_BUTTON:
- transposeInLandscape = true;
- // Fall through, zero button and two button modes behave the same.
- case ZERO_BUTTON: {
- final int startX;
- final int startY;
- final int endX;
- final int endY;
- if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
- // Swipe from the bottom left to the bottom right of the screen.
- startX = 0;
- startY = getSwipeStartY();
- endX = mLauncher.getDevice().getDisplayWidth();
- endY = startY;
- } else {
- // Swipe from the bottom right to the top right of the screen.
- startX = getSwipeStartX();
- startY = mLauncher.getRealDisplaySize().y - 1;
- endX = startX;
- endY = 0;
- }
- final boolean isZeroButton = mLauncher.getNavigationModel()
- == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
- mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState,
- launcherWasVisible && isZeroButton
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
- break;
- }
-
- case THREE_BUTTON:
- // Double press the recents button.
- UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps");
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
- mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL);
- mLauncher.getOverview();
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
- recentsButton.click();
- break;
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
- }
-
protected String getSwipeHeightRequestName() {
return TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 223ae29..588b6b8 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -27,7 +27,7 @@
import java.util.List;
/**
- * Common overview pane for both Launcher and fallback recents
+ * Common overview panel for both Launcher and fallback recents
*/
public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
private static final int FLINGS_FOR_DISMISS_LIMIT = 40;
@@ -135,4 +135,19 @@
public boolean hasTasks() {
return getTasks().size() > 0;
}
+
+ /**
+ * Gets Overview Actions.
+ *
+ * @return The Overview Actions
+ */
+ @NonNull
+ public OverviewActions getOverviewActions() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get overview actions")) {
+ verifyActiveContainer();
+ UiObject2 overviewActions = mLauncher.waitForLauncherObject("action_buttons");
+ return new OverviewActions(overviewActions, mLauncher);
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index c06e254..0060844 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -16,8 +16,6 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
-
import androidx.annotation.NonNull;
/**
@@ -65,8 +63,4 @@
return true;
}
- @Override
- protected int getExpectedStateForQuickSwitch() {
- return QUICK_SWITCH_STATE_ORDINAL;
- }
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 4e2ed11..a77c1c6 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -156,6 +156,7 @@
public static final int WAIT_TIME_MS = 10000;
public static final int LONG_WAIT_TIME_MS = 60000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
+ private static final String ANDROID_PACKAGE = "android";
private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
@@ -174,8 +175,7 @@
private Runnable mOnLauncherCrashed;
private static Pattern getTouchEventPattern(String prefix, String action) {
- // The pattern includes sanity checks that we don't get a multi-touch events or other
- // surprises.
+ // The pattern includes checks that we don't get a multi-touch events or other surprises.
return Pattern.compile(
prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
+ ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount=1");
@@ -931,6 +931,14 @@
return waitForObjectBySelector(getOverviewObjectSelector(resName));
}
+ @NonNull
+ UiObject2 waitForAndroidObject(String resId) {
+ final UiObject2 object = mDevice.wait(
+ Until.findObject(By.res(ANDROID_PACKAGE, resId)), WAIT_TIME_MS);
+ assertNotNull("Can't find a android object with id: " + resId, object);
+ return object;
+ }
+
private UiObject2 waitForObjectBySelector(BySelector selector) {
final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
assertNotNull("Can't find a view in Launcher, selector: " + selector, object);
@@ -1307,6 +1315,11 @@
TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+ boolean overviewShareEnabled() {
+ return getTestInfo(TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED).getBoolean(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
private void disableSensorRotation() {
getTestInfo(TestProtocol.REQUEST_MOCK_SENSOR_ROTATION);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
new file mode 100644
index 0000000..a30a404
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 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.tapl;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.launcher3.testing.TestProtocol;
+
+/**
+ * View containing overview actions
+ */
+public class OverviewActions {
+ private final UiObject2 mOverviewActions;
+ private final LauncherInstrumentation mLauncher;
+
+ OverviewActions(UiObject2 overviewActions, LauncherInstrumentation launcherInstrumentation) {
+ this.mOverviewActions = overviewActions;
+ this.mLauncher = launcherInstrumentation;
+ }
+
+ /**
+ * Clicks screenshot button and closes screenshot ui.
+ */
+ @NonNull
+ public Overview clickAndDismissScreenshot() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to click screenshot button and exit screenshot ui")) {
+ UiObject2 screenshot = mLauncher.waitForObjectInContainer(mOverviewActions,
+ "action_screenshot");
+ mLauncher.clickLauncherObject(screenshot);
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "clicked screenshot button")) {
+ UiObject2 closeScreenshot = mLauncher.waitForSystemUiObject(
+ "global_screenshot_dismiss_image");
+ if (mLauncher.getNavigationModel()
+ != LauncherInstrumentation.NavigationModel.THREE_BUTTON) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS,
+ LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS,
+ LauncherInstrumentation.EVENT_TOUCH_UP_TIS);
+ }
+ closeScreenshot.click();
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
+ "dismissed screenshot")) {
+ return new Overview(mLauncher);
+ }
+ }
+ }
+ }
+
+ /**
+ * Click share button, then drags sharesheet down to remove it.
+ *
+ * Share is currently hidden behind flag, test is kept in case share becomes a default feature.
+ * If share is completely removed then remove this test as well.
+ */
+ @NonNull
+ public Overview clickAndDismissShare() {
+ if (mLauncher.overviewShareEnabled()) {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to click share button and dismiss sharesheet")) {
+ UiObject2 share = mLauncher.waitForObjectInContainer(mOverviewActions,
+ "action_share");
+ mLauncher.clickLauncherObject(share);
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "clicked share button")) {
+ mLauncher.waitForAndroidObject("contentPanel");
+ mLauncher.getDevice().pressBack();
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
+ "dismissed sharesheet")) {
+ return new Overview(mLauncher);
+ }
+ }
+ }
+ }
+ return new Overview(mLauncher);
+ }
+
+ /**
+ * Click select button
+ *
+ * @return The select mode buttons that are now shown instead of action buttons.
+ */
+ @NonNull
+ public SelectModeButtons clickSelect() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c =
+ mLauncher.addContextLayer("want to click select button")) {
+ UiObject2 select = mLauncher.waitForObjectInContainer(mOverviewActions,
+ "action_select");
+ mLauncher.clickLauncherObject(select);
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "clicked select button")) {
+ return getSelectModeButtons();
+ }
+
+ }
+ }
+
+ /**
+ * Gets the Select Mode Buttons.
+ *
+ * @return The Select Mode Buttons.
+ */
+ @NonNull
+ private SelectModeButtons getSelectModeButtons() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get select mode buttons")) {
+ UiObject2 selectModeButtons = mLauncher.waitForLauncherObject("select_mode_buttons");
+ return new SelectModeButtons(selectModeButtons, mLauncher);
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
new file mode 100644
index 0000000..3507418
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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.tapl;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * View containing select mode buttons
+ */
+public class SelectModeButtons {
+ private final UiObject2 mSelectModeButtons;
+ private final LauncherInstrumentation mLauncher;
+
+ SelectModeButtons(UiObject2 selectModeButtons,
+ LauncherInstrumentation launcherInstrumentation) {
+ mSelectModeButtons = selectModeButtons;
+ mLauncher = launcherInstrumentation;
+ }
+
+ /**
+ * Click close button.
+ */
+ @NonNull
+ public Overview clickClose() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c =
+ mLauncher.addContextLayer("want to click close button")) {
+ UiObject2 close = mLauncher.waitForObjectInContainer(mSelectModeButtons, "close");
+ mLauncher.clickLauncherObject(close);
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "clicked close button")) {
+ return new Overview(mLauncher);
+ }
+ }
+ }
+
+ /**
+ * Click feedback button.
+ */
+ @NonNull
+ public Background clickFeedback() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c =
+ mLauncher.addContextLayer("want to click feedback button")) {
+ UiObject2 feedback = mLauncher.waitForObjectInContainer(mSelectModeButtons, "feedback");
+ mLauncher.clickLauncherObject(feedback);
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "clicked feedback button")) {
+ return new Background(mLauncher);
+ }
+ }
+ }
+}