Snap for 7721244 from 81a3e6e7e7 to sc-v2-release
Change-Id: I37084fe830ca0a31e7e65d84d8c50a460cda3f51
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
determines how many thumbnails will be fetched in the background. -->
|
||||
<integer name="recentsThumbnailCacheSize">3</integer>
|
||||
<integer name="recentsIconCacheSize">12</integer>
|
||||
<integer name="recentsScrollHapticMinGapMillis">20</integer>
|
||||
|
||||
<!-- Assistant Gesture -->
|
||||
<integer name="assistant_gesture_min_time_threshold">200</integer>
|
||||
|
||||
@@ -77,6 +77,7 @@ public class TaskbarUnfoldAnimationController {
|
||||
@Override
|
||||
public void onTransitionFinished() {
|
||||
mMoveFromCenterAnimator.onTransitionFinished();
|
||||
mMoveFromCenterAnimator.clearRegisteredViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
|
||||
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
@@ -38,11 +38,11 @@ import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.OverviewToHomeAnim;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
|
||||
+11
-2
@@ -41,7 +41,7 @@ import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
|
||||
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
@@ -67,14 +67,15 @@ import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.touch.BaseSwipeDetector;
|
||||
import com.android.launcher3.touch.BothAxesSwipeDetector;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
import com.android.quickstep.util.WorkspaceRevealAnim;
|
||||
import com.android.quickstep.views.LauncherRecentsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
* Handles quick switching to a recent task from the home screen. To give as much flexibility to
|
||||
@@ -398,6 +399,14 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
||||
nonOverviewAnim.setFloatValues(startProgress, endProgress);
|
||||
mNonOverviewAnim.dispatchOnStart();
|
||||
}
|
||||
if (targetState == QUICK_SWITCH) {
|
||||
// Navigating to quick switch, add scroll feedback since the first time is not
|
||||
// considered a scroll by the RecentsView.
|
||||
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(
|
||||
RecentsView.SCROLL_VIBRATION_PRIMITIVE,
|
||||
RecentsView.SCROLL_VIBRATION_PRIMITIVE_SCALE,
|
||||
RecentsView.SCROLL_VIBRATION_FALLBACK);
|
||||
}
|
||||
|
||||
nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
|
||||
mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState));
|
||||
|
||||
+13
-1
@@ -22,6 +22,7 @@ import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_BOTH
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.os.SystemClock;
|
||||
import android.os.VibrationEffect;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -41,6 +42,7 @@ import com.android.launcher3.util.FlingBlockCheck;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
||||
@@ -55,6 +57,12 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
private static final long MIN_TASK_DISMISS_ANIMATION_DURATION = 300;
|
||||
private static final long MAX_TASK_DISMISS_ANIMATION_DURATION = 600;
|
||||
|
||||
public static final int TASK_DISMISS_VIBRATION_PRIMITIVE =
|
||||
Utilities.ATLEAST_R ? VibrationEffect.Composition.PRIMITIVE_TICK : -1;
|
||||
public static final float TASK_DISMISS_VIBRATION_PRIMITIVE_SCALE = 1f;
|
||||
public static final VibrationEffect TASK_DISMISS_VIBRATION_FALLBACK =
|
||||
VibratorWrapper.EFFECT_TEXTURE_TICK;
|
||||
|
||||
protected final T mActivity;
|
||||
private final SingleAxisSwipeDetector mDetector;
|
||||
private final RecentsView mRecentsView;
|
||||
@@ -334,10 +342,10 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
fling = false;
|
||||
}
|
||||
PagedOrientationHandler orientationHandler = mRecentsView.getPagedOrientationHandler();
|
||||
boolean goingUp = orientationHandler.isGoingUp(velocity, mIsRtl);
|
||||
float progress = mCurrentAnimation.getProgressFraction();
|
||||
float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress();
|
||||
if (fling) {
|
||||
boolean goingUp = orientationHandler.isGoingUp(velocity, mIsRtl);
|
||||
goingToEnd = goingUp == mCurrentAnimationIsGoingUp;
|
||||
} else {
|
||||
goingToEnd = interpolatedProgress > SUCCESS_TRANSITION_PROGRESS;
|
||||
@@ -357,6 +365,10 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
mCurrentAnimation.startWithVelocity(mActivity, goingToEnd,
|
||||
velocity * orientationHandler.getSecondaryTranslationDirectionFactor(),
|
||||
mEndDisplacement, animationDuration);
|
||||
if (goingUp && goingToEnd) {
|
||||
VibratorWrapper.INSTANCE.get(mActivity).vibrate(TASK_DISMISS_VIBRATION_PRIMITIVE,
|
||||
TASK_DISMISS_VIBRATION_PRIMITIVE_SCALE, TASK_DISMISS_VIBRATION_FALLBACK);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearState() {
|
||||
|
||||
@@ -36,7 +36,6 @@ import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
|
||||
@@ -46,6 +45,7 @@ import static com.android.quickstep.GestureState.STATE_END_TARGET_SET;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_CANCELED;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
@@ -92,7 +92,6 @@ import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.tracing.InputConsumerProto;
|
||||
import com.android.launcher3.tracing.SwipeHandlerProto;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
@@ -112,6 +111,7 @@ import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
import com.android.quickstep.util.SwipePipToHomeAnimator;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -945,6 +945,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
|
||||
// Notify swipe-to-home (recents animation) is finished
|
||||
SystemUiProxy.INSTANCE.get(mContext).notifySwipeToHomeFinished();
|
||||
LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();
|
||||
break;
|
||||
case RECENTS:
|
||||
mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
|
||||
@@ -1805,8 +1806,13 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mGestureState.updateLastStartedTaskId(taskId);
|
||||
boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
|
||||
.contains(taskId);
|
||||
boolean isOldTaskSplit = LauncherSplitScreenListener.INSTANCE.getNoCreate()
|
||||
.getRunningSplitTaskIds().length > 0;
|
||||
nextTask.launchTask(success -> {
|
||||
resultCallback.accept(success);
|
||||
if (isOldTaskSplit) {
|
||||
SystemUiProxy.INSTANCE.getNoCreate().exitSplitScreen(taskId);
|
||||
}
|
||||
if (success) {
|
||||
if (hasTaskPreviouslyAppeared) {
|
||||
onRestartPreviouslyAppearedTask();
|
||||
|
||||
@@ -32,6 +32,7 @@ import androidx.annotation.UiThread;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
|
||||
import com.android.quickstep.util.LauncherSplitScreenListener;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -157,6 +158,7 @@ public class OverviewCommandHelper {
|
||||
}
|
||||
if (cmd.type == TYPE_HOME) {
|
||||
mService.startActivity(mOverviewComponentObserver.getHomeIntent());
|
||||
LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@@ -175,6 +177,7 @@ public class OverviewCommandHelper {
|
||||
return launchTask(recents, getNextTask(recents), cmd);
|
||||
case TYPE_HOME:
|
||||
recents.startHome();
|
||||
LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,10 +533,17 @@ public class SystemUiProxy implements ISystemUiProxy,
|
||||
}
|
||||
}
|
||||
|
||||
public void exitSplitScreen() {
|
||||
/**
|
||||
* To be called whenever the user exits out of split screen apps (either by launching another
|
||||
* app or by swiping home)
|
||||
* @param topTaskId The taskId of the new app that was launched. System will then move this task
|
||||
* to the front of what the user sees while removing all other split stages.
|
||||
* If swiping to home (or there is no task to put at the top), can pass in -1.
|
||||
*/
|
||||
public void exitSplitScreen(int topTaskId) {
|
||||
if (mSplitScreen != null) {
|
||||
try {
|
||||
mSplitScreen.exitSplitScreen();
|
||||
mSplitScreen.exitSplitScreen(topTaskId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call exitSplitScreen");
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ import androidx.dynamicanimation.animation.SpringForce;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
|
||||
/** Forked from platform/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java. */
|
||||
public class EdgeBackGesturePanel extends View {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.android.quickstep.interaction;
|
||||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_COMPLETED;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_BAD_ANGLE;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT;
|
||||
@@ -26,6 +25,7 @@ import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestu
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.OVERVIEW_GESTURE_COMPLETED;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE;
|
||||
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
@@ -47,11 +47,11 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.NavBarPosition;
|
||||
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
|
||||
/** Utility class to handle Home and Assistant gestures. */
|
||||
|
||||
@@ -44,8 +44,6 @@ public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
|
||||
if (frozen) {
|
||||
mPersistentGroupedIds = getRunningSplitTaskIds();
|
||||
} else {
|
||||
// TODO(b/198310766) Need to also explicitly exit split screen if
|
||||
// we're not currently viewing split screened apps
|
||||
mPersistentGroupedIds = EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -53,8 +51,11 @@ public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
|
||||
|
||||
/**
|
||||
* Gets set to current split taskIDs whenever the task list is frozen, and set to empty array
|
||||
* whenever task list unfreezes.
|
||||
* When not null, this indicates that we need to load a GroupedTaskView as the most recent
|
||||
* whenever task list unfreezes. This also gets set to empty array whenever the user swipes to
|
||||
* home - in that case the task list does not unfreeze immediately after the gesture, so it's
|
||||
* done via {@link #notifySwipingToHome()}.
|
||||
*
|
||||
* When not empty, this indicates that we need to load a GroupedTaskView as the most recent
|
||||
* page, so user can quickswitch back to a grouped task.
|
||||
*/
|
||||
private int[] mPersistentGroupedIds;
|
||||
@@ -140,6 +141,18 @@ public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/** Notifies SystemUi to remove any split screen state */
|
||||
public void notifySwipingToHome() {
|
||||
boolean hasSplitTasks = LauncherSplitScreenListener.INSTANCE.getNoCreate()
|
||||
.getPersistentSplitIds().length > 0;
|
||||
if (!hasSplitTasks) {
|
||||
return;
|
||||
}
|
||||
|
||||
SystemUiProxy.INSTANCE.getNoCreate().exitSplitScreen(-1);
|
||||
mPersistentGroupedIds = EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private void resetTaskId(StagedSplitTaskPosition taskPosition) {
|
||||
taskPosition.taskId = -1;
|
||||
}
|
||||
|
||||
+35
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2021 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,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.util;
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static android.os.VibrationEffect.createPredefined;
|
||||
import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
|
||||
@@ -21,15 +21,20 @@ import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.media.AudioAttributes;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
|
||||
/**
|
||||
* Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
|
||||
*/
|
||||
@@ -39,8 +44,15 @@ public class VibratorWrapper {
|
||||
public static final MainThreadInitializedObject<VibratorWrapper> INSTANCE =
|
||||
new MainThreadInitializedObject<>(VibratorWrapper::new);
|
||||
|
||||
public static final AudioAttributes VIBRATION_ATTRS = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||
.build();
|
||||
|
||||
public static final VibrationEffect EFFECT_CLICK =
|
||||
createPredefined(VibrationEffect.EFFECT_CLICK);
|
||||
public static final VibrationEffect EFFECT_TEXTURE_TICK =
|
||||
VibrationEffect.createPredefined(VibrationEffect.EFFECT_TEXTURE_TICK);
|
||||
|
||||
/**
|
||||
* Haptic when entering overview.
|
||||
@@ -78,7 +90,27 @@ public class VibratorWrapper {
|
||||
/** Vibrates with the given effect if haptic feedback is available and enabled. */
|
||||
public void vibrate(VibrationEffect vibrationEffect) {
|
||||
if (mHasVibrator && mIsHapticFeedbackEnabled) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(vibrationEffect));
|
||||
UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(vibrationEffect, VIBRATION_ATTRS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vibrates with a single primitive, if supported, or use a fallback effect instead. This only
|
||||
* vibrates if haptic feedback is available and enabled.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void vibrate(int primitiveId, float primitiveScale, VibrationEffect fallbackEffect) {
|
||||
if (mHasVibrator && mIsHapticFeedbackEnabled) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
if (Utilities.ATLEAST_R && primitiveId >= 0
|
||||
&& mVibrator.areAllPrimitivesSupported(primitiveId)) {
|
||||
mVibrator.vibrate(VibrationEffect.startComposition()
|
||||
.addPrimitive(primitiveId, primitiveScale)
|
||||
.compose(), VIBRATION_ATTRS);
|
||||
} else {
|
||||
mVibrator.vibrate(fallbackEffect, VIBRATION_ATTRS);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,9 @@ import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.VibrationEffect;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
@@ -160,6 +162,7 @@ import com.android.quickstep.util.SplitSelectStateController;
|
||||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.util.VibratorWrapper;
|
||||
import com.android.systemui.plugins.ResourceProvider;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
@@ -244,6 +247,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
};
|
||||
|
||||
public static final int SCROLL_VIBRATION_PRIMITIVE =
|
||||
Utilities.ATLEAST_S ? VibrationEffect.Composition.PRIMITIVE_LOW_TICK : -1;
|
||||
public static final float SCROLL_VIBRATION_PRIMITIVE_SCALE = 0.6f;
|
||||
public static final VibrationEffect SCROLL_VIBRATION_FALLBACK =
|
||||
VibratorWrapper.EFFECT_TEXTURE_TICK;
|
||||
|
||||
/**
|
||||
* Can be used to tint the color of the RecentsView to simulate a scrim that can views
|
||||
* excluded from. Really should be a proper scrim.
|
||||
@@ -397,6 +406,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
|
||||
protected final ACTIVITY_TYPE mActivity;
|
||||
private final float mFastFlingVelocity;
|
||||
private final int mScrollHapticMinGapMillis;
|
||||
private final RecentsModel mModel;
|
||||
private final int mGridSideMargin;
|
||||
private final ClearAllButton mClearAllButton;
|
||||
@@ -443,6 +453,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
private ObjectAnimator mTintingAnimator;
|
||||
|
||||
private int mOverScrollShift = 0;
|
||||
private long mScrollLastHapticTimestamp;
|
||||
|
||||
/**
|
||||
* TODO: Call reloadIdNeeded in onTaskStackChanged.
|
||||
@@ -629,6 +640,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
final int rotation = mActivity.getDisplay().getRotation();
|
||||
mOrientationState.setRecentsRotation(rotation);
|
||||
|
||||
mScrollHapticMinGapMillis = getResources()
|
||||
.getInteger(R.integer.recentsScrollHapticMinGapMillis);
|
||||
mFastFlingVelocity = getResources()
|
||||
.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
|
||||
mModel = RecentsModel.INSTANCE.get(context);
|
||||
@@ -1228,6 +1241,25 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEdgeAbsorbingScroll() {
|
||||
vibrateForScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollOverPageChanged() {
|
||||
vibrateForScroll();
|
||||
}
|
||||
|
||||
private void vibrateForScroll() {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
if (now - mScrollLastHapticTimestamp > mScrollHapticMinGapMillis) {
|
||||
mScrollLastHapticTimestamp = now;
|
||||
VibratorWrapper.INSTANCE.get(mContext).vibrate(SCROLL_VIBRATION_PRIMITIVE,
|
||||
SCROLL_VIBRATION_PRIMITIVE_SCALE, SCROLL_VIBRATION_FALLBACK);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
|
||||
// Enables swiping to the left or right only if the task overlay is not modal.
|
||||
@@ -2002,9 +2034,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
/**
|
||||
* Called only when a swipe-up gesture from an app has completed. Only called after
|
||||
* {@link #onGestureAnimationStart} and {@link #onGestureAnimationEnd()}.
|
||||
*
|
||||
* TODO(b/198310766) Need to also explicitly exit split screen if
|
||||
* the swipe up was to home
|
||||
*/
|
||||
public void onSwipeUpAnimationSuccess() {
|
||||
animateUpTaskIconScale();
|
||||
|
||||
@@ -99,6 +99,7 @@ import com.android.quickstep.TaskThumbnailCache;
|
||||
import com.android.quickstep.TaskUtils;
|
||||
import com.android.quickstep.TaskViewUtils;
|
||||
import com.android.quickstep.util.CancellableTask;
|
||||
import com.android.quickstep.util.LauncherSplitScreenListener;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.TaskCornerRadius;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
@@ -693,8 +694,13 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
TestLogging.recordEvent(
|
||||
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
|
||||
ActivityOptionsWrapper opts = mActivity.getActivityLaunchOptions(this, null);
|
||||
boolean isOldTaskSplit = LauncherSplitScreenListener.INSTANCE.getNoCreate()
|
||||
.getPersistentSplitIds().length > 0;
|
||||
if (ActivityManagerWrapper.getInstance()
|
||||
.startActivityFromRecents(mTask.key, opts.options)) {
|
||||
if (isOldTaskSplit) {
|
||||
SystemUiProxy.INSTANCE.getNoCreate().exitSplitScreen(mTask.key.id);
|
||||
}
|
||||
RecentsView recentsView = getRecentsView();
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && recentsView.getRunningTaskViewId() != -1) {
|
||||
recentsView.onTaskLaunchedInLiveTileMode();
|
||||
|
||||
@@ -108,6 +108,8 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
// relative scroll position unchanged in updateCurrentPageScroll. Cleared when snapping to a
|
||||
// page.
|
||||
protected int mCurrentPageScrollDiff;
|
||||
// The current page the PagedView is scrolling over on it's way to the destination page.
|
||||
protected int mCurrentScrollOverPage;
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
protected int mNextPage = INVALID_PAGE;
|
||||
@@ -180,6 +182,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
|
||||
mScroller = new OverScroller(context, SCROLL);
|
||||
mCurrentPage = 0;
|
||||
mCurrentScrollOverPage = 0;
|
||||
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
||||
mTouchSlop = configuration.getScaledTouchSlop();
|
||||
@@ -437,6 +440,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
}
|
||||
int prevPage = overridePrevPage != INVALID_PAGE ? overridePrevPage : mCurrentPage;
|
||||
mCurrentPage = validateNewPage(currentPage);
|
||||
mCurrentScrollOverPage = mCurrentPage;
|
||||
updateCurrentPageScroll();
|
||||
notifyPageSwitchListener(prevPage);
|
||||
invalidate();
|
||||
@@ -557,9 +561,11 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
if (newPos < mMinScroll && oldPos >= mMinScroll) {
|
||||
mEdgeGlowLeft.onAbsorb((int) mScroller.getCurrVelocity());
|
||||
mScroller.abortAnimation();
|
||||
onEdgeAbsorbingScroll();
|
||||
} else if (newPos > mMaxScroll && oldPos <= mMaxScroll) {
|
||||
mEdgeGlowRight.onAbsorb((int) mScroller.getCurrVelocity());
|
||||
mScroller.abortAnimation();
|
||||
onEdgeAbsorbingScroll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,6 +583,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
sendScrollAccessibilityEvent();
|
||||
int prevPage = mCurrentPage;
|
||||
mCurrentPage = validateNewPage(mNextPage);
|
||||
mCurrentScrollOverPage = mCurrentPage;
|
||||
mNextPage = INVALID_PAGE;
|
||||
notifyPageSwitchListener(prevPage);
|
||||
|
||||
@@ -766,7 +773,8 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
childStart += primaryDimension + getChildGap();
|
||||
|
||||
// This makes sure that the space is added after the page, not after each panel
|
||||
if (i % panelCount == panelCount - 1) {
|
||||
int lastPanel = mIsRtl ? 0 : panelCount - 1;
|
||||
if (i % panelCount == lastPanel) {
|
||||
childStart += mPageSpacing;
|
||||
}
|
||||
}
|
||||
@@ -837,6 +845,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
public void onViewRemoved(View child) {
|
||||
super.onViewRemoved(child);
|
||||
mCurrentPage = validateNewPage(mCurrentPage);
|
||||
mCurrentScrollOverPage = mCurrentPage;
|
||||
dispatchPageCountChanged();
|
||||
}
|
||||
|
||||
@@ -1408,6 +1417,20 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
|
||||
protected void onNotSnappingToPageInFreeScroll() { }
|
||||
|
||||
/**
|
||||
* Called when the view edges absorb part of the scroll. Subclasses can override this
|
||||
* to provide custom behavior during animation.
|
||||
*/
|
||||
protected void onEdgeAbsorbingScroll() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the current page closest to the center of the screen changes as part of the
|
||||
* scroll. Subclasses can override this to provide custom behavior during scroll.
|
||||
*/
|
||||
protected void onScrollOverPageChanged() {
|
||||
}
|
||||
|
||||
protected boolean shouldFlingForVelocity(int velocity) {
|
||||
float threshold = mAllowEasyFling ? mEasyFlingThresholdVelocity : mFlingThresholdVelocity;
|
||||
return Math.abs(velocity) > threshold;
|
||||
@@ -1553,7 +1576,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
return getDisplacementFromScreenCenter(childIndex, screenCenter);
|
||||
}
|
||||
|
||||
private int getScreenCenter(int primaryScroll) {
|
||||
protected int getScreenCenter(int primaryScroll) {
|
||||
float primaryScale = mOrientationHandler.getPrimaryScale(this);
|
||||
float primaryPivot = mOrientationHandler.getPrimaryValue(getPivotX(), getPivotY());
|
||||
int pageOrientationSize = mOrientationHandler.getMeasuredSize(this);
|
||||
@@ -1691,6 +1714,15 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
return mAllowOverScroll;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
|
||||
int newDestinationPage = getDestinationPage();
|
||||
if (newDestinationPage >= 0 && newDestinationPage != mCurrentScrollOverPage) {
|
||||
mCurrentScrollOverPage = newDestinationPage;
|
||||
onScrollOverPageChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAccessibilityClassName() {
|
||||
// Some accessibility services have special logic for ScrollView. Since we provide same
|
||||
|
||||
@@ -338,15 +338,17 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
int paddingBottom = grid.cellLayoutBottomPaddingPx;
|
||||
|
||||
int panelCount = getPanelCount();
|
||||
int rightPanelModulus = mIsRtl ? 0 : panelCount - 1;
|
||||
int leftPanelModulus = mIsRtl ? panelCount - 1 : 0;
|
||||
int numberOfScreens = mScreenOrder.size();
|
||||
for (int i = 0; i < numberOfScreens; i++) {
|
||||
int paddingLeft = paddingLeftRight;
|
||||
int paddingRight = paddingLeftRight;
|
||||
if (panelCount > 1) {
|
||||
if (i % panelCount == 0) { // left side panel
|
||||
if (i % panelCount == leftPanelModulus) {
|
||||
paddingLeft = paddingLeftRight;
|
||||
paddingRight = 0;
|
||||
} else if (i % panelCount == panelCount - 1) { // right side panel
|
||||
} else if (i % panelCount == rightPanelModulus) {
|
||||
paddingLeft = 0;
|
||||
paddingRight = paddingLeftRight;
|
||||
} else { // middle panel
|
||||
@@ -2453,21 +2455,32 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
}
|
||||
|
||||
int nextPage = getNextPage();
|
||||
if (layout == null && !isPageInTransition()) {
|
||||
layout = verifyInsidePage(nextPage + (mIsRtl ? 1 : -1), Math.min(centerX, d.x), d.y);
|
||||
IntSet pageIndexesToVerify = IntSet.wrap(nextPage - 1, nextPage + 1);
|
||||
if (isTwoPanelEnabled()) {
|
||||
// If two panel is enabled, users can also drag items to nextPage + 2
|
||||
pageIndexesToVerify.add(nextPage + 2);
|
||||
}
|
||||
|
||||
if (layout == null && !isPageInTransition()) {
|
||||
layout = verifyInsidePage(nextPage + (mIsRtl ? -1 : 1), Math.max(centerX, d.x), d.y);
|
||||
int touchX = (int) Math.min(centerX, d.x);
|
||||
int touchY = d.y;
|
||||
|
||||
// Go through the pages and check if the dragged item is inside one of them
|
||||
for (int pageIndex : pageIndexesToVerify) {
|
||||
if (layout != null || isPageInTransition()) {
|
||||
break;
|
||||
}
|
||||
layout = verifyInsidePage(pageIndex, touchX, touchY);
|
||||
}
|
||||
|
||||
// If two panel is enabled, users can also drag items to currentPage + 2
|
||||
if (isTwoPanelEnabled() && layout == null && !isPageInTransition()) {
|
||||
layout = verifyInsidePage(nextPage + (mIsRtl ? -2 : 2), Math.max(centerX, d.x), d.y);
|
||||
}
|
||||
|
||||
// Always pick the current page.
|
||||
// If the dragged item isn't located in one of the pages above, the icon will stay on the
|
||||
// current screen. For two panel pick the closest panel on the current screen,
|
||||
// on one panel just choose the current page.
|
||||
if (layout == null && nextPage >= 0 && nextPage < getPageCount()) {
|
||||
if (isTwoPanelEnabled()) {
|
||||
nextPage = getScreenCenter(getScrollX()) > touchX
|
||||
? (mIsRtl ? nextPage + 1 : nextPage) // left side
|
||||
: (mIsRtl ? nextPage : nextPage + 1); // right side
|
||||
}
|
||||
layout = (CellLayout) getChildAt(nextPage);
|
||||
}
|
||||
if (layout != mDragTargetLayout) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.text.TextUtils;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
@@ -44,6 +45,7 @@ public class DeviceGridState {
|
||||
public static final int TYPE_PHONE = 0;
|
||||
public static final int TYPE_MULTI_DISPLAY = 1;
|
||||
public static final int TYPE_TABLET = 2;
|
||||
public static final IntSet COMPATIBLE_TYPES = IntSet.wrap(TYPE_PHONE, TYPE_MULTI_DISPLAY);
|
||||
|
||||
private final String mGridSizeString;
|
||||
private final int mNumHotseat;
|
||||
@@ -109,7 +111,9 @@ public class DeviceGridState {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DeviceGridState that = (DeviceGridState) o;
|
||||
return mNumHotseat == that.mNumHotseat
|
||||
&& mDeviceType == that.mDeviceType
|
||||
&& (mDeviceType == that.mDeviceType
|
||||
|| (COMPATIBLE_TYPES.contains(mDeviceType)
|
||||
&& COMPATIBLE_TYPES.contains(that.mDeviceType)))
|
||||
&& Objects.equals(mGridSizeString, that.mGridSizeString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
|
||||
import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
|
||||
import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;
|
||||
|
||||
@@ -29,6 +30,7 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
@@ -44,6 +46,7 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -57,12 +60,15 @@ import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.config.FlagTogglerPrefUi;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -104,6 +110,7 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
|
||||
initFlags();
|
||||
loadPluginPrefs();
|
||||
maybeAddSandboxCategory();
|
||||
addOnboardingPrefsCatergory();
|
||||
|
||||
if (getActivity() != null) {
|
||||
getActivity().setTitle("Developer Options");
|
||||
@@ -153,6 +160,15 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
|
||||
}
|
||||
});
|
||||
|
||||
if (getArguments() != null) {
|
||||
String filter = getArguments().getString(EXTRA_FRAGMENT_ARG_KEY);
|
||||
// Normally EXTRA_FRAGMENT_ARG_KEY is used to highlight the preference with the given
|
||||
// key. This is a slight variation where we instead filter by the human-readable titles.
|
||||
if (filter != null) {
|
||||
filterBox.setText(filter);
|
||||
}
|
||||
}
|
||||
|
||||
View listView = getListView();
|
||||
final int bottomPadding = listView.getPaddingBottom();
|
||||
listView.setOnApplyWindowInsetsListener((v, insets) -> {
|
||||
@@ -355,6 +371,28 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
|
||||
sandboxCategory.addPreference(launchSandboxModeTutorialPreference);
|
||||
}
|
||||
|
||||
private void addOnboardingPrefsCatergory() {
|
||||
PreferenceCategory onboardingCategory = newCategory("Onboarding Flows");
|
||||
onboardingCategory.setSummary("Reset these if you want to see the education again.");
|
||||
for (Map.Entry<String, String[]> titleAndKeys : OnboardingPrefs.ALL_PREF_KEYS.entrySet()) {
|
||||
String title = titleAndKeys.getKey();
|
||||
String[] keys = titleAndKeys.getValue();
|
||||
Preference onboardingPref = new Preference(getContext());
|
||||
onboardingPref.setTitle(title);
|
||||
onboardingPref.setSummary("Tap to reset");
|
||||
onboardingPref.setOnPreferenceClickListener(preference -> {
|
||||
SharedPreferences.Editor sharedPrefsEdit = Utilities.getPrefs(getContext()).edit();
|
||||
for (String key : keys) {
|
||||
sharedPrefsEdit.remove(key);
|
||||
}
|
||||
sharedPrefsEdit.apply();
|
||||
Toast.makeText(getContext(), "Reset " + title, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
});
|
||||
onboardingCategory.addPreference(onboardingPref);
|
||||
}
|
||||
}
|
||||
|
||||
private String toName(String action) {
|
||||
String str = action.replace("com.android.systemui.action.PLUGIN_", "")
|
||||
.replace("com.android.launcher3.action.PLUGIN_", "");
|
||||
|
||||
@@ -39,6 +39,14 @@ public class OnboardingPrefs<T extends Launcher> {
|
||||
public static final String SEARCH_EDU_SEEN = "launcher.search_edu_seen";
|
||||
public static final String SEARCH_SNACKBAR_COUNT = "launcher.keyboard_snackbar_count";
|
||||
public static final String TASKBAR_EDU_SEEN = "launcher.taskbar_edu_seen";
|
||||
// When adding a new key, add it here as well, to be able to reset it from Developer Options.
|
||||
public static final Map<String, String[]> ALL_PREF_KEYS = Map.of(
|
||||
"All Apps Bounce", new String[] { HOME_BOUNCE_SEEN, HOME_BOUNCE_COUNT },
|
||||
"Hybrid Hotseat Education", new String[] { HOTSEAT_DISCOVERY_TIP_COUNT,
|
||||
HOTSEAT_LONGPRESS_TIP_SEEN },
|
||||
"Search Education", new String[] { SEARCH_EDU_SEEN, SEARCH_SNACKBAR_COUNT },
|
||||
"Taskbar Education", new String[] { TASKBAR_EDU_SEEN }
|
||||
);
|
||||
|
||||
/**
|
||||
* Events that either have happened or have not (booleans).
|
||||
|
||||
Reference in New Issue
Block a user