Loading AndroidManifest-common.xml +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.VIBRATE"/> <!-- for rotating surface by arbitrary degree --> <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> Loading quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +8 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.taskbar.LauncherTaskbarUIController; import com.android.launcher3.uioverrides.QuickstepLauncher; Loading @@ -62,6 +63,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch private static final long TRANSLATION_ANIM_MIN_DURATION_MS = 80; private static final float TRANSLATION_ANIM_VELOCITY_DP_PER_MS = 0.8f; private final VibratorWrapper mVibratorWrapper; private final RecentsView mRecentsView; private final MotionPauseDetector mMotionPauseDetector; private final float mMotionPauseMinDisplacement; Loading @@ -82,6 +84,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch mRecentsView = l.getOverviewPanel(); mMotionPauseDetector = new MotionPauseDetector(l); mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop(); mVibratorWrapper = VibratorWrapper.INSTANCE.get(l.getApplicationContext()); } @Override Loading Loading @@ -188,6 +191,11 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch // need to manually set the duration to a reasonable value. animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */)); } if (FeatureFlags.ENABLE_HAPTICS_ALL_APPS.get() && ((mFromState == NORMAL && mToState == ALL_APPS) || (mFromState == ALL_APPS && mToState == NORMAL)) && isFling) { mVibratorWrapper.vibrateForDragBump(); } } private void onMotionPauseDetected() { Loading src/com/android/launcher3/allapps/AllAppsTransitionController.java +70 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.util.FloatProperty; import android.view.HapticFeedbackConstants; import android.view.View; Loading @@ -47,17 +48,21 @@ import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatedFloat; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.AllAppsSwipeController; import com.android.launcher3.util.MultiPropertyFactory; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.Themes; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.views.ScrimView; /** Loading @@ -78,6 +83,8 @@ public class AllAppsTransitionController private static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200; private static final float NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.1f; private static final float SWIPE_DRAG_COMMIT_THRESHOLD = 1 - AllAppsSwipeController.ALL_APPS_STATE_TRANSITION_MANUAL; public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS = new FloatProperty<AllAppsTransitionController>("allAppsProgress") { Loading Loading @@ -181,6 +188,7 @@ public class AllAppsTransitionController private boolean mIsTablet; private boolean mHasScaleEffect; private final VibratorWrapper mVibratorWrapper; public AllAppsTransitionController(Launcher l) { mLauncher = l; Loading @@ -193,6 +201,7 @@ public class AllAppsTransitionController setShiftRange(dp.allAppsShiftRange); mLauncher.addOnDeviceProfileChangeListener(this); mVibratorWrapper = VibratorWrapper.INSTANCE.get(mLauncher.getApplicationContext()); } public float getShiftRange() { Loading Loading @@ -311,6 +320,11 @@ public class AllAppsTransitionController /** * Creates an animation which updates the vertical transition progress and updates all the * dependent UI using various animation events * * This method also dictates where along the progress the haptics should be played. As the user * scrolls up from workspace or down from AllApps, a drag haptic is being played until the * commit point where it plays a commit haptic. Where we play the haptics differs when going * from workspace -> allApps and vice versa. */ @Override public void setStateWithAnimation(LauncherState toState, Loading Loading @@ -339,6 +353,20 @@ public class AllAppsTransitionController }); } if(FeatureFlags.ENABLE_HAPTICS_ALL_APPS.get() && config.userControlled && Utilities.ATLEAST_S) { if (toState == ALL_APPS) { builder.addOnFrameListener( new VibrationAnimatorUpdateListener(this, mVibratorWrapper, SWIPE_DRAG_COMMIT_THRESHOLD, 1)); } else { builder.addOnFrameListener( new VibrationAnimatorUpdateListener(this, mVibratorWrapper, 0, SWIPE_DRAG_COMMIT_THRESHOLD)); } builder.addEndListener(mVibratorWrapper::cancelVibrate); } float targetProgress = toState.getVerticalProgress(mLauncher); if (Float.compare(mProgress, targetProgress) == 0) { setAlphas(toState, config, builder); Loading @@ -356,7 +384,7 @@ public class AllAppsTransitionController setAlphas(toState, config, builder); if (ALL_APPS.equals(toState) && mLauncher.isInState(NORMAL)) { if (ALL_APPS.equals(toState) && mLauncher.isInState(NORMAL) && !(Utilities.ATLEAST_S)) { mLauncher.getAppsView().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } Loading Loading @@ -494,4 +522,45 @@ public class AllAppsTransitionController } } } /** * This VibrationAnimatorUpdateListener class takes in four parameters, a controller, start * threshold, end threshold, and a Vibrator wrapper. We use the progress given by the controller * as it gives an accurate progress that dictates where the vibrator should vibrate. * Note: once the user begins a gesture and does the commit haptic, there should not be anymore * haptics played for that gesture. */ private static class VibrationAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener { private final VibratorWrapper mVibratorWrapper; private final AllAppsTransitionController mController; private final float mStartThreshold; private final float mEndThreshold; private boolean mHasCommitted; VibrationAnimatorUpdateListener(AllAppsTransitionController controller, VibratorWrapper vibratorWrapper, float startThreshold, float endThreshold) { mController = controller; mVibratorWrapper = vibratorWrapper; mStartThreshold = startThreshold; mEndThreshold = endThreshold; } @Override public void onAnimationUpdate(ValueAnimator animation) { if (mHasCommitted) { return; } float currentProgress = AllAppsTransitionController.ALL_APPS_PROGRESS.get(mController); if (currentProgress > mStartThreshold && currentProgress < mEndThreshold) { mVibratorWrapper.vibrateForDragTexture(); } else if (!(currentProgress == 0 || currentProgress == 1)) { // This check guards against committing at the location of the start of the gesture mVibratorWrapper.vibrateForDragCommit(); mHasCommitted = true; } } } } src/com/android/launcher3/config/FeatureFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -371,6 +371,8 @@ public final class FeatureFlags { "ENABLE_LAUNCH_FROM_STAGED_APP", true, "Enable the ability to tap a staged app during split select to launch it in full screen" ); public static final BooleanFlag ENABLE_HAPTICS_ALL_APPS = getDebugFlag( "ENABLE_HAPTICS_ALL_APPS", false, "Enables haptics opening/closing All apps"); public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag( "ENABLE_FORCED_MONO_ICON", false, Loading src/com/android/launcher3/touch/AllAppsSwipeController.java +1 −4 Original line number Diff line number Diff line Loading @@ -129,10 +129,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { Interpolators.clampToProgress( Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1f), ALL_APPS_STATE_TRANSITION_ATOMIC, 1f); public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_MANUAL = Interpolators.clampToProgress( Interpolators.mapToProgress(LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, 1f), ALL_APPS_STATE_TRANSITION_MANUAL, 1f); public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_MANUAL = LINEAR; // -------- Loading Loading
AndroidManifest-common.xml +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.VIBRATE"/> <!-- for rotating surface by arbitrary degree --> <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> Loading
quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +8 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.taskbar.LauncherTaskbarUIController; import com.android.launcher3.uioverrides.QuickstepLauncher; Loading @@ -62,6 +63,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch private static final long TRANSLATION_ANIM_MIN_DURATION_MS = 80; private static final float TRANSLATION_ANIM_VELOCITY_DP_PER_MS = 0.8f; private final VibratorWrapper mVibratorWrapper; private final RecentsView mRecentsView; private final MotionPauseDetector mMotionPauseDetector; private final float mMotionPauseMinDisplacement; Loading @@ -82,6 +84,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch mRecentsView = l.getOverviewPanel(); mMotionPauseDetector = new MotionPauseDetector(l); mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop(); mVibratorWrapper = VibratorWrapper.INSTANCE.get(l.getApplicationContext()); } @Override Loading Loading @@ -188,6 +191,11 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch // need to manually set the duration to a reasonable value. animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */)); } if (FeatureFlags.ENABLE_HAPTICS_ALL_APPS.get() && ((mFromState == NORMAL && mToState == ALL_APPS) || (mFromState == ALL_APPS && mToState == NORMAL)) && isFling) { mVibratorWrapper.vibrateForDragBump(); } } private void onMotionPauseDetected() { Loading
src/com/android/launcher3/allapps/AllAppsTransitionController.java +70 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.util.FloatProperty; import android.view.HapticFeedbackConstants; import android.view.View; Loading @@ -47,17 +48,21 @@ import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatedFloat; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.AllAppsSwipeController; import com.android.launcher3.util.MultiPropertyFactory; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.Themes; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.views.ScrimView; /** Loading @@ -78,6 +83,8 @@ public class AllAppsTransitionController private static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200; private static final float NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.1f; private static final float SWIPE_DRAG_COMMIT_THRESHOLD = 1 - AllAppsSwipeController.ALL_APPS_STATE_TRANSITION_MANUAL; public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS = new FloatProperty<AllAppsTransitionController>("allAppsProgress") { Loading Loading @@ -181,6 +188,7 @@ public class AllAppsTransitionController private boolean mIsTablet; private boolean mHasScaleEffect; private final VibratorWrapper mVibratorWrapper; public AllAppsTransitionController(Launcher l) { mLauncher = l; Loading @@ -193,6 +201,7 @@ public class AllAppsTransitionController setShiftRange(dp.allAppsShiftRange); mLauncher.addOnDeviceProfileChangeListener(this); mVibratorWrapper = VibratorWrapper.INSTANCE.get(mLauncher.getApplicationContext()); } public float getShiftRange() { Loading Loading @@ -311,6 +320,11 @@ public class AllAppsTransitionController /** * Creates an animation which updates the vertical transition progress and updates all the * dependent UI using various animation events * * This method also dictates where along the progress the haptics should be played. As the user * scrolls up from workspace or down from AllApps, a drag haptic is being played until the * commit point where it plays a commit haptic. Where we play the haptics differs when going * from workspace -> allApps and vice versa. */ @Override public void setStateWithAnimation(LauncherState toState, Loading Loading @@ -339,6 +353,20 @@ public class AllAppsTransitionController }); } if(FeatureFlags.ENABLE_HAPTICS_ALL_APPS.get() && config.userControlled && Utilities.ATLEAST_S) { if (toState == ALL_APPS) { builder.addOnFrameListener( new VibrationAnimatorUpdateListener(this, mVibratorWrapper, SWIPE_DRAG_COMMIT_THRESHOLD, 1)); } else { builder.addOnFrameListener( new VibrationAnimatorUpdateListener(this, mVibratorWrapper, 0, SWIPE_DRAG_COMMIT_THRESHOLD)); } builder.addEndListener(mVibratorWrapper::cancelVibrate); } float targetProgress = toState.getVerticalProgress(mLauncher); if (Float.compare(mProgress, targetProgress) == 0) { setAlphas(toState, config, builder); Loading @@ -356,7 +384,7 @@ public class AllAppsTransitionController setAlphas(toState, config, builder); if (ALL_APPS.equals(toState) && mLauncher.isInState(NORMAL)) { if (ALL_APPS.equals(toState) && mLauncher.isInState(NORMAL) && !(Utilities.ATLEAST_S)) { mLauncher.getAppsView().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } Loading Loading @@ -494,4 +522,45 @@ public class AllAppsTransitionController } } } /** * This VibrationAnimatorUpdateListener class takes in four parameters, a controller, start * threshold, end threshold, and a Vibrator wrapper. We use the progress given by the controller * as it gives an accurate progress that dictates where the vibrator should vibrate. * Note: once the user begins a gesture and does the commit haptic, there should not be anymore * haptics played for that gesture. */ private static class VibrationAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener { private final VibratorWrapper mVibratorWrapper; private final AllAppsTransitionController mController; private final float mStartThreshold; private final float mEndThreshold; private boolean mHasCommitted; VibrationAnimatorUpdateListener(AllAppsTransitionController controller, VibratorWrapper vibratorWrapper, float startThreshold, float endThreshold) { mController = controller; mVibratorWrapper = vibratorWrapper; mStartThreshold = startThreshold; mEndThreshold = endThreshold; } @Override public void onAnimationUpdate(ValueAnimator animation) { if (mHasCommitted) { return; } float currentProgress = AllAppsTransitionController.ALL_APPS_PROGRESS.get(mController); if (currentProgress > mStartThreshold && currentProgress < mEndThreshold) { mVibratorWrapper.vibrateForDragTexture(); } else if (!(currentProgress == 0 || currentProgress == 1)) { // This check guards against committing at the location of the start of the gesture mVibratorWrapper.vibrateForDragCommit(); mHasCommitted = true; } } } }
src/com/android/launcher3/config/FeatureFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -371,6 +371,8 @@ public final class FeatureFlags { "ENABLE_LAUNCH_FROM_STAGED_APP", true, "Enable the ability to tap a staged app during split select to launch it in full screen" ); public static final BooleanFlag ENABLE_HAPTICS_ALL_APPS = getDebugFlag( "ENABLE_HAPTICS_ALL_APPS", false, "Enables haptics opening/closing All apps"); public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag( "ENABLE_FORCED_MONO_ICON", false, Loading
src/com/android/launcher3/touch/AllAppsSwipeController.java +1 −4 Original line number Diff line number Diff line Loading @@ -129,10 +129,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController { Interpolators.clampToProgress( Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1f), ALL_APPS_STATE_TRANSITION_ATOMIC, 1f); public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_MANUAL = Interpolators.clampToProgress( Interpolators.mapToProgress(LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, 1f), ALL_APPS_STATE_TRANSITION_MANUAL, 1f); public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_MANUAL = LINEAR; // -------- Loading