Merge "Validate source rect hint for enter PIP in gesture nav" into main
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 14605d8..7e824ec 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -67,6 +67,7 @@
<application
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
+ android:name="com.android.launcher3.LauncherApplication"
android:fullBackupOnly="true"
android:backupInForeground="true"
android:fullBackupContent="@xml/backupscheme"
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index d2be94a..e77d2c6 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -77,7 +77,6 @@
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Color;
@@ -187,9 +186,6 @@
*/
public static final int STATUS_BAR_TRANSITION_PRE_DELAY = 96;
- private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
- "android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS";
-
public static final long APP_LAUNCH_DURATION = 500;
private static final long APP_LAUNCH_ALPHA_DURATION = 50;
@@ -292,8 +288,8 @@
mLauncher.addOnDeviceProfileChangeListener(this);
- if (supportsSSplashScreen()) {
- mTaskStartParams = new LinkedHashMap<Integer, Pair<Integer, Integer>>(MAX_NUM_TASKS) {
+ if (ENABLE_SHELL_STARTING_SURFACE) {
+ mTaskStartParams = new LinkedHashMap<>(MAX_NUM_TASKS) {
@Override
protected boolean removeEldestEntry(Entry<Integer, Pair<Integer, Integer>> entry) {
return size() > MAX_NUM_TASKS;
@@ -681,7 +677,7 @@
mDragLayer.getLocationOnScreen(dragLayerBounds);
final boolean hasSplashScreen;
- if (supportsSSplashScreen()) {
+ if (ENABLE_SHELL_STARTING_SURFACE) {
int taskId = openingTargets.getFirstAppTargetTaskId();
Pair<Integer, Integer> defaultParams = Pair.create(STARTING_WINDOW_TYPE_NONE, 0);
Pair<Integer, Integer> taskParams =
@@ -926,7 +922,7 @@
RemoteAnimationTarget openingTarget = openingTargets.getFirstAppTarget();
int fallbackBackgroundColor = 0;
- if (openingTarget != null && supportsSSplashScreen()) {
+ if (openingTarget != null && ENABLE_SHELL_STARTING_SURFACE) {
fallbackBackgroundColor = mTaskStartParams.containsKey(openingTarget.taskId)
? mTaskStartParams.get(openingTarget.taskId).second : 0;
mTaskStartParams.remove(openingTarget.taskId);
@@ -1102,11 +1098,9 @@
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
- if (hasControlRemoteAppTransitionPermission()) {
- RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- addRemoteAnimations(definition);
- mLauncher.registerRemoteAnimations(definition);
- }
+ RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
+ addRemoteAnimations(definition);
+ mLauncher.registerRemoteAnimations(definition);
}
/**
@@ -1144,28 +1138,27 @@
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
- if (hasControlRemoteAppTransitionPermission()) {
- mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
- mLauncherOpenTransition = new RemoteTransition(
- new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
- false /* startAtFrontOfQueue */).toRemoteTransition(),
- mLauncher.getIApplicationThread(), "QuickstepLaunchHome");
- TransitionFilter homeCheck = new TransitionFilter();
- // No need to handle the transition that also dismisses keyguard.
- homeCheck.mNotFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
- homeCheck.mRequirements =
- new TransitionFilter.Requirement[]{new TransitionFilter.Requirement(),
- new TransitionFilter.Requirement()};
- homeCheck.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
- homeCheck.mRequirements[0].mTopActivity = mLauncher.getComponentName();
- homeCheck.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
- homeCheck.mRequirements[0].mOrder = CONTAINER_ORDER_TOP;
- homeCheck.mRequirements[1].mActivityType = ACTIVITY_TYPE_STANDARD;
- homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
- SystemUiProxy.INSTANCE.get(mLauncher)
- .registerRemoteTransition(mLauncherOpenTransition, homeCheck);
- }
+ mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
+ mLauncherOpenTransition = new RemoteTransition(
+ new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
+ false /* startAtFrontOfQueue */).toRemoteTransition(),
+ mLauncher.getIApplicationThread(), "QuickstepLaunchHome");
+
+ TransitionFilter homeCheck = new TransitionFilter();
+ // No need to handle the transition that also dismisses keyguard.
+ homeCheck.mNotFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
+ homeCheck.mRequirements =
+ new TransitionFilter.Requirement[]{new TransitionFilter.Requirement(),
+ new TransitionFilter.Requirement()};
+ homeCheck.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
+ homeCheck.mRequirements[0].mTopActivity = mLauncher.getComponentName();
+ homeCheck.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+ homeCheck.mRequirements[0].mOrder = CONTAINER_ORDER_TOP;
+ homeCheck.mRequirements[1].mActivityType = ACTIVITY_TYPE_STANDARD;
+ homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+ SystemUiProxy.INSTANCE.get(mLauncher)
+ .registerRemoteTransition(mLauncherOpenTransition, homeCheck);
if (mBackAnimationController != null) {
mBackAnimationController.registerBackCallbacks(mHandler);
}
@@ -1183,15 +1176,13 @@
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
- if (hasControlRemoteAppTransitionPermission()) {
- mLauncher.unregisterRemoteAnimations();
+ mLauncher.unregisterRemoteAnimations();
- // Also clear strong references to the runners registered with the remote animation
- // definition so we don't have to wait for the system gc
- mWallpaperOpenRunner = null;
- mAppLaunchRunner = null;
- mKeyguardGoingAwayRunner = null;
- }
+ // Also clear strong references to the runners registered with the remote animation
+ // definition so we don't have to wait for the system gc
+ mWallpaperOpenRunner = null;
+ mAppLaunchRunner = null;
+ mKeyguardGoingAwayRunner = null;
}
protected void unregisterRemoteTransitions() {
@@ -1201,13 +1192,11 @@
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
- if (hasControlRemoteAppTransitionPermission()) {
- if (mLauncherOpenTransition == null) return;
- SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition(
- mLauncherOpenTransition);
- mLauncherOpenTransition = null;
- mWallpaperOpenTransitionRunner = null;
- }
+ if (mLauncherOpenTransition == null) return;
+ SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition(
+ mLauncherOpenTransition);
+ mLauncherOpenTransition = null;
+ mWallpaperOpenTransitionRunner = null;
if (mBackAnimationController != null) {
mBackAnimationController.unregisterBackCallbacks();
mBackAnimationController = null;
@@ -1553,20 +1542,6 @@
return closingAnimator;
}
- private boolean supportsSSplashScreen() {
- return hasControlRemoteAppTransitionPermission()
- && Utilities.ATLEAST_S
- && ENABLE_SHELL_STARTING_SURFACE;
- }
-
- /**
- * Returns true if we have permission to control remote app transisions
- */
- public boolean hasControlRemoteAppTransitionPermission() {
- return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
- == PackageManager.PERMISSION_GRANTED;
- }
-
private void addCujInstrumentation(Animator anim, int cuj) {
anim.addListener(new AnimationSuccessListener() {
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 3dc30dc..5f58de5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -18,8 +18,9 @@
import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import android.content.Context;
@@ -172,12 +173,14 @@
@DrawableRes
private int getAllAppsButton(boolean isTransientTaskbar) {
+ boolean shouldSelectTransientIcon = (isTransientTaskbar || ENABLE_TASKBAR_PINNING.get())
+ && !mActivityContext.isThreeButtonNav();
if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
- return isTransientTaskbar
+ return shouldSelectTransientIcon
? R.drawable.ic_transient_taskbar_all_apps_search_button
: R.drawable.ic_taskbar_all_apps_search_button;
} else {
- return isTransientTaskbar
+ return shouldSelectTransientIcon
? R.drawable.ic_transient_taskbar_all_apps_button
: R.drawable.ic_taskbar_all_apps_button;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 7d88f05..4aa00e1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -1021,7 +1021,7 @@
@Override
public boolean supportsAdaptiveIconAnimation(View clickedView) {
- return mAppTransitionManager.hasControlRemoteAppTransitionPermission();
+ return true;
}
@Override
@@ -1056,10 +1056,7 @@
@Override
public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
- ActivityOptionsWrapper activityOptions =
- mAppTransitionManager.hasControlRemoteAppTransitionPermission()
- ? mAppTransitionManager.getActivityLaunchOptions(v)
- : super.getActivityLaunchOptions(v, item);
+ ActivityOptionsWrapper activityOptions = mAppTransitionManager.getActivityLaunchOptions(v);
if (mLastTouchUpTime > 0) {
activityOptions.options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER,
mLastTouchUpTime);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index 5253e7a..a922ed1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -24,6 +24,10 @@
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT;
import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE;
import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_TIMEOUT_MS;
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
@@ -118,9 +122,7 @@
if (FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()) {
addAllAppsFromOverviewCatergory();
}
- if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
- addCustomLpnhCatergory();
- }
+ addCustomLpnhCategory();
if (getActivity() != null) {
getActivity().setTitle("Developer Options");
@@ -423,13 +425,25 @@
105, 500, 100, ALL_APPS_OVERVIEW_THRESHOLD));
}
- private void addCustomLpnhCatergory() {
+ private void addCustomLpnhCategory() {
PreferenceCategory category = newCategory("Long Press Nav Handle Config");
- category.addPreference(createSeekBarPreference("Slop multiplier (applied to edge slop, "
- + "which is generally already 50% higher than touch slop)",
- 25, 200, 100, LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE));
- category.addPreference(createSeekBarPreference("Trigger milliseconds",
- 100, 500, 1, LONG_PRESS_NAV_HANDLE_TIMEOUT_MS));
+ if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
+ category.addPreference(createSeekBarPreference("Slop multiplier (applied to edge slop, "
+ + "which is generally already 50% higher than touch slop)",
+ 25, 200, 100, LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE));
+ category.addPreference(createSeekBarPreference("Trigger milliseconds",
+ 100, 500, 1, LONG_PRESS_NAV_HANDLE_TIMEOUT_MS));
+ }
+ if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get()) {
+ category.addPreference(createSeekBarPreference("Haptic hint start scale",
+ 0, 100, 100, LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT));
+ category.addPreference(createSeekBarPreference("Haptic hint end scale",
+ 0, 100, 100, LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT));
+ category.addPreference(createSeekBarPreference("Haptic hint scale exponent",
+ 1, 5, 1, LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT));
+ category.addPreference(createSeekBarPreference("Haptic hint iterations (12 ms each)",
+ 0, 100, 1, LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS));
+ }
}
/**
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
index 7a2b343..14305cf 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
@@ -46,4 +46,19 @@
public @Nullable Runnable getLongPressRunnable() {
return null;
}
+
+ /**
+ * Called when nav handle gesture starts. Returns true if long press nav handle is enabled and
+ * supported.
+ */
+ public boolean canStartTouch() {
+ return false;
+ }
+
+ /**
+ * Called when nav handle gesture is finished by the user lifting their finger or the system
+ * cancelling the touch for some other reason.
+ */
+ public void onTouchFinished() {
+ }
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index 1af4bad..f11e537 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -80,7 +80,8 @@
mCurrentDownEvent.recycle();
}
mCurrentDownEvent = MotionEvent.obtain(ev);
- if (isInNavBarHorizontalArea(ev.getRawX())) {
+ if (isInNavBarHorizontalArea(ev.getRawX())
+ && mNavHandleLongPressHandler.canStartTouch()) {
MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress,
mLongPressTimeout);
}
@@ -133,6 +134,7 @@
private void cancelLongPress() {
MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress);
+ mNavHandleLongPressHandler.onTouchFinished();
}
private boolean isInNavBarHorizontalArea(float x) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index f6a9440..12a8bd9 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -20,9 +20,9 @@
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.Utilities.squaredHypot;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
import android.content.Context;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 92b942d..beb10ef 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -23,9 +23,10 @@
import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.enableOverviewIconMenu;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -115,8 +116,6 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
-import kotlin.Unit;
-
import java.lang.annotation.Retention;
import java.util.Arrays;
import java.util.Collections;
@@ -125,6 +124,8 @@
import java.util.function.Consumer;
import java.util.stream.Stream;
+import kotlin.Unit;
+
/**
* A task in the Recents view.
*/
@@ -445,7 +446,7 @@
boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
|| DesktopTaskView.DESKTOP_MODE_SUPPORTED;
- boolean cursorHoverStatesEnabled = FeatureFlags.enableCursorHoverStates();
+ boolean cursorHoverStatesEnabled = enableCursorHoverStates();
setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled);
@@ -561,7 +562,7 @@
@Override
public boolean onInterceptHoverEvent(MotionEvent event) {
- if (FeatureFlags.enableCursorHoverStates()) {
+ if (enableCursorHoverStates()) {
// avoid triggering hover event on child elements which would cause HOVER_EXIT for this
// task view
return true;
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 61f1f74..d45c225 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -16,7 +16,6 @@
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
@@ -45,7 +44,6 @@
import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -226,7 +224,7 @@
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testSwitchToOverviewWithStashedTaskbar() throws Exception {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+ try {
startTestAppsWithCheck();
// Set ignoreTaskbarVisibility, as transient taskbar will be stashed after app launch.
mLauncher.setIgnoreTaskbarVisibility(true);
@@ -356,6 +354,7 @@
@PortraitLandscape
@TaskbarModeSwitch(mode = PERSISTENT)
@PlatinumTest(focusArea = "launcher")
+ @ScreenRecord
public void testOverviewForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
index fc23a05..db23cc0 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
@@ -15,14 +15,15 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
+import static org.junit.Assume.assumeTrue;
+
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.util.TestUtil;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import org.junit.Test;
@@ -35,42 +36,32 @@
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testShowTaskbarUnstashHintOnHover() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
}
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testUnstashTaskbarOnScreenBottomEdgeHover() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
}
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testHoverBelowHintedTaskbarToUnstash() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
}
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testClickHoveredTaskbarToGoHome() throws Exception {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
}
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d7b50a0..ddcb1e6 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,8 +17,9 @@
package com.android.launcher3;
import static android.text.Layout.Alignment.ALIGN_NORMAL;
+
+import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4a9add4..b629ec2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2600,21 +2600,20 @@
.logEnd(isBindSync
? LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC
: LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC);
- // In the first rootview's onDraw after onInitialBindComplete(), log end of startup latency.
+ MAIN_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
+ mStartupLatencyLogger
+ .logEnd(LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION)
+ .log()
+ .reset();
+ if (mIsColdStartupAfterReboot) {
+ Trace.endAsyncSection(COLD_STARTUP_TRACE_METHOD_NAME,
+ COLD_STARTUP_TRACE_COOKIE);
+ }
+ });
getRootView().getViewTreeObserver().addOnDrawListener(
new ViewTreeObserver.OnDrawListener() {
-
@Override
public void onDraw() {
- mStartupLatencyLogger
- .logEnd(LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION)
- .log()
- .reset();
- if (mIsColdStartupAfterReboot) {
- Trace.endAsyncSection(COLD_STARTUP_TRACE_METHOD_NAME,
- COLD_STARTUP_TRACE_COOKIE);
- }
-
MAIN_EXECUTOR.getHandler().postAtFrontOfQueue(
() -> getRootView().getViewTreeObserver()
.removeOnDrawListener(this));
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 8d19040..34bfdb7 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -64,12 +64,6 @@
public class LauncherAppState implements SafeCloseable {
public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
- public static final String KEY_ICON_STATE = "pref_icon_shape_path";
- public static final String KEY_ALL_APPS_OVERVIEW_THRESHOLD = "pref_all_apps_overview_threshold";
- public static final String KEY_LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE =
- "pref_long_press_nav_handle_slop_multiplier";
- public static final String KEY_LONG_PRESS_NAV_HANDLE_TIMEOUT_MS =
- "pref_long_press_nav_handle_timeout_ms";
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<LauncherAppState> INSTANCE =
diff --git a/src/com/android/launcher3/LauncherApplication.java b/src/com/android/launcher3/LauncherApplication.java
new file mode 100644
index 0000000..40873be
--- /dev/null
+++ b/src/com/android/launcher3/LauncherApplication.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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;
+
+import android.app.Application;
+
+/**
+ * Main application class for Launcher
+ */
+public class LauncherApplication extends Application {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ MainProcessInitializer.initialize(this);
+ }
+}
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index 9a0d02a..c6a9283 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -297,31 +297,59 @@
@JvmField
val ICON_STATE =
nonRestorableItem(
- LauncherAppState.KEY_ICON_STATE,
+ "pref_icon_shape_path",
"",
EncryptionType.MOVE_TO_DEVICE_PROTECTED
)
@JvmField
val ALL_APPS_OVERVIEW_THRESHOLD =
nonRestorableItem(
- LauncherAppState.KEY_ALL_APPS_OVERVIEW_THRESHOLD,
+ "pref_all_apps_overview_threshold",
180,
EncryptionType.MOVE_TO_DEVICE_PROTECTED
)
@JvmField
val LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE =
- nonRestorableItem(
- LauncherAppState.KEY_LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE,
- 100,
- EncryptionType.MOVE_TO_DEVICE_PROTECTED
- )
+ nonRestorableItem(
+ "pref_long_press_nav_handle_slop_multiplier",
+ 100,
+ EncryptionType.MOVE_TO_DEVICE_PROTECTED
+ )
@JvmField
val LONG_PRESS_NAV_HANDLE_TIMEOUT_MS =
- nonRestorableItem(
- LauncherAppState.KEY_LONG_PRESS_NAV_HANDLE_TIMEOUT_MS,
- ViewConfiguration.getLongPressTimeout(),
- EncryptionType.MOVE_TO_DEVICE_PROTECTED
- )
+ nonRestorableItem(
+ "pref_long_press_nav_handle_timeout_ms",
+ ViewConfiguration.getLongPressTimeout(),
+ EncryptionType.MOVE_TO_DEVICE_PROTECTED
+ )
+ @JvmField
+ val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT =
+ nonRestorableItem(
+ "pref_long_press_nav_handle_haptic_hint_start_scale_percent",
+ 0,
+ EncryptionType.MOVE_TO_DEVICE_PROTECTED
+ )
+ @JvmField
+ val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT =
+ nonRestorableItem(
+ "pref_long_press_nav_handle_haptic_hint_end_scale_percent",
+ 50,
+ EncryptionType.MOVE_TO_DEVICE_PROTECTED
+ )
+ @JvmField
+ val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT =
+ nonRestorableItem(
+ "pref_long_press_nav_handle_haptic_hint_scale_exponent",
+ 2,
+ EncryptionType.MOVE_TO_DEVICE_PROTECTED
+ )
+ @JvmField
+ val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS =
+ nonRestorableItem(
+ "pref_long_press_nav_handle_haptic_hint_iterations",
+ 40,
+ EncryptionType.MOVE_TO_DEVICE_PROTECTED
+ )
@JvmField
val THEMED_ICONS =
backedUpItem(Themes.KEY_THEMED_ICONS, false, EncryptionType.MOVE_TO_DEVICE_PROTECTED)
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 440e146..4e0ba62 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -33,7 +33,6 @@
import android.util.Log;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.widget.LauncherWidgetHolder;
@@ -44,8 +43,6 @@
public class LauncherProvider extends ContentProvider {
private static final String TAG = "LauncherProvider";
- public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
-
/**
* $ adb shell dumpsys activity provider com.android.launcher3
*/
@@ -60,13 +57,6 @@
@Override
public boolean onCreate() {
- if (FeatureFlags.IS_STUDIO_BUILD) {
- Log.d(TAG, "Launcher process started");
- }
-
- // The content provider exists for the entire duration of the launcher main process and
- // is the first component to get created.
- MainProcessInitializer.initialize(getContext().getApplicationContext());
return true;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index c09a5b9..278e4e5 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -373,7 +373,9 @@
new VibrationAnimatorUpdateListener(this, mVibratorWrapper,
0, SWIPE_DRAG_COMMIT_THRESHOLD));
}
- builder.addEndListener(mVibratorWrapper::cancelVibrate);
+ builder.addEndListener((unused) -> {
+ mVibratorWrapper.cancelVibrate();
+ });
}
float targetProgress = toState.getVerticalProgress(mLauncher);
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 5b44069..2ca8a1e 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -262,6 +262,10 @@
getReleaseFlag(282993230, "ENABLE_LONG_PRESS_NAV_HANDLE", TEAMFOOD,
"Enables long pressing on the bottom bar nav handle to trigger events.");
+ public static final BooleanFlag ENABLE_SEARCH_HAPTIC_HINT =
+ getReleaseFlag(303023676, "ENABLE_SEARCH_HAPTIC_HINT", TEAMFOOD,
+ "Enables haptic hint when long pressing on the bottom bar nav handle.");
+
// TODO(Block 17): Clean up flags
public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583,
"ENABLE_TASKBAR_PINNING", DISABLED,
@@ -319,15 +323,6 @@
+ "waiting for SystemUI and then merging the SystemUI progress whenever we "
+ "start receiving the events");
- // Aconfig migration complete for ENABLE_CURSOR_HOVER_STATES.
- @VisibleForTesting
- public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650,
- "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD,
- "Enables cursor hover states for certain elements.");
- public static boolean enableCursorHoverStates() {
- return ENABLE_CURSOR_HOVER_STATES.get() || Flags.enableCursorHoverStates();
- }
-
// TODO(Block 24): Clean up flags
public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455,
"ENABLE_NEW_MIGRATION_LOGIC", ENABLED,
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index d00d901..cb1dc4f 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -16,7 +16,7 @@
package com.android.launcher3.folder;
-import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION;
diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
index ae5d8d4..18200f6 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2023 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.graphics;
import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
@@ -21,6 +36,7 @@
import android.os.Messenger;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.GridOption;
@@ -70,7 +86,11 @@
private static final int MESSAGE_ID_UPDATE_PREVIEW = 1337;
- private final ArrayMap<IBinder, PreviewLifecycleObserver> mActivePreviews = new ArrayMap<>();
+ /**
+ * Here we use the IBinder and the screen ID as the key of the active previews.
+ */
+ private final ArrayMap<Pair<IBinder, Integer>, PreviewLifecycleObserver> mActivePreviews =
+ new ArrayMap<>();
@Override
public boolean onCreate() {
@@ -176,11 +196,10 @@
try {
PreviewSurfaceRenderer renderer = new PreviewSurfaceRenderer(getContext(), request);
- // Destroy previous
- destroyObserver(mActivePreviews.get(renderer.getHostToken()));
-
observer = new PreviewLifecycleObserver(renderer);
- mActivePreviews.put(renderer.getHostToken(), observer);
+ // Destroy previous
+ destroyObserver(mActivePreviews.get(observer.getIdentifier()));
+ mActivePreviews.put(observer.getIdentifier(), observer);
renderer.loadAsync();
renderer.getHostToken().linkToDeath(observer, 0);
@@ -210,9 +229,9 @@
observer.destroyed = true;
observer.renderer.getHostToken().unlinkToDeath(observer, 0);
Executors.MAIN_EXECUTOR.execute(observer.renderer::destroy);
- PreviewLifecycleObserver cached = mActivePreviews.get(observer.renderer.getHostToken());
+ PreviewLifecycleObserver cached = mActivePreviews.get(observer.getIdentifier());
if (cached == observer) {
- mActivePreviews.remove(observer.renderer.getHostToken());
+ mActivePreviews.remove(observer.getIdentifier());
}
}
@@ -242,5 +261,14 @@
public void binderDied() {
destroyObserver(this);
}
+
+ /**
+ * Returns a key that should make the PreviewSurfaceRenderer unique and if two of them have
+ * the same key they will be treated as the same PreviewSurfaceRenderer. Primary this is
+ * used to prevent memory leaks by removing the old PreviewSurfaceRenderer.
+ */
+ public Pair<IBinder, Integer> getIdentifier() {
+ return new Pair<>(renderer.getHostToken(), renderer.getDisplayId());
+ }
}
}
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index aebcdd4..683354b 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -114,12 +114,17 @@
mDisplay = context.getSystemService(DisplayManager.class)
.getDisplay(bundle.getInt(KEY_DISPLAY_ID));
- mSurfaceControlViewHost = MAIN_EXECUTOR.submit(() -> new SurfaceControlViewHost(mContext,
- context.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY),
- mHostToken)).get(5, TimeUnit.SECONDS);
+ mSurfaceControlViewHost = MAIN_EXECUTOR.submit(() ->
+ new SurfaceControlViewHost(mContext, context.getSystemService(DisplayManager.class)
+ .getDisplay(DEFAULT_DISPLAY), mHostToken)
+ ).get(5, TimeUnit.SECONDS);
mOnDestroyCallbacks.add(mSurfaceControlViewHost::release);
}
+ public int getDisplayId() {
+ return mDisplay.getDisplayId();
+ }
+
public IBinder getHostToken() {
return mHostToken;
}
@@ -225,7 +230,7 @@
PreviewContext previewContext = new PreviewContext(inflationContext, idp);
// Copy existing data to preview DB
LauncherDbUtils.copyTable(LauncherAppState.getInstance(mContext)
- .getModel().getModelDbController().getDb(),
+ .getModel().getModelDbController().getDb(),
TABLE_NAME,
LauncherAppState.getInstance(previewContext)
.getModel().getModelDbController().getDb(),
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
index 91945ca..80a9bae 100644
--- a/src/com/android/launcher3/util/VibratorWrapper.java
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -18,6 +18,10 @@
import static android.os.VibrationEffect.createPredefined;
import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@@ -35,10 +39,9 @@
import androidx.annotation.Nullable;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.PendingAnimation;
-
-import java.util.function.Consumer;
+import com.android.launcher3.config.FeatureFlags;
/**
* Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
@@ -70,7 +73,7 @@
private final VibrationEffect mBumpEffect;
@Nullable
- private final VibrationEffect mAssistEffect;
+ private final VibrationEffect mSearchEffect;
private long mLastDragTime;
private final int mThresholdUntilNextDragCallMillis;
@@ -80,12 +83,14 @@
*/
public static final VibrationEffect OVERVIEW_HAPTIC = EFFECT_CLICK;
+ private final Context mContext;
private final Vibrator mVibrator;
private final boolean mHasVibrator;
private boolean mIsHapticFeedbackEnabled;
private VibratorWrapper(Context context) {
+ mContext = context;
mVibrator = context.getSystemService(Vibrator.class);
mHasVibrator = mVibrator.hasVibrator();
if (mHasVibrator) {
@@ -133,14 +138,20 @@
if (Utilities.ATLEAST_R && mVibrator.areAllPrimitivesSupported(
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
VibrationEffect.Composition.PRIMITIVE_TICK)) {
- // quiet ramp, short pause, then sharp tick
- mAssistEffect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50)
- .compose();
+ if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get()) {
+ mSearchEffect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f)
+ .compose();
+ } else {
+ // quiet ramp, short pause, then sharp tick
+ mSearchEffect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50)
+ .compose();
+ }
} else {
// fallback for devices without composition support
- mAssistEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
+ mSearchEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
}
}
@@ -184,20 +195,10 @@
}
/**
- * The assist haptic is used to be called when an assistant is invoked
- */
- public void vibrateForAssist() {
- if (mAssistEffect != null) {
- vibrate(mAssistEffect);
- }
- }
-
- /**
* This should be used to cancel a haptic in case where the haptic shouldn't be vibrating. For
- * example, when no animation is happening but a vibrator happens to be vibrating still. Need
- * boolean parameter for {@link PendingAnimation#addEndListener(Consumer)}.
+ * example, when no animation is happening but a vibrator happens to be vibrating still.
*/
- public void cancelVibrate(boolean unused) {
+ public void cancelVibrate() {
UI_HELPER_EXECUTOR.execute(mVibrator::cancel);
// reset dragTexture timestamp to be able to play dragTexture again whenever cancelled
mLastDragTime = 0;
@@ -233,4 +234,37 @@
});
}
}
+
+ /** Indicates that search has been invoked. */
+ public void vibrateForSearch() {
+ if (mSearchEffect != null) {
+ vibrate(mSearchEffect);
+ }
+ }
+
+ /** Indicates that search will be invoked if the current gesture is maintained. */
+ public void vibrateForSearchHint() {
+ if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get() && Utilities.ATLEAST_S
+ && mVibrator.areAllPrimitivesSupported(
+ VibrationEffect.Composition.PRIMITIVE_LOW_TICK)) {
+ float startScale = LauncherPrefs.get(mContext).get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT) / 100f;
+ float endScale = LauncherPrefs.get(mContext).get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT) / 100f;
+ int scaleExponent = LauncherPrefs.get(mContext).get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT);
+ int iterations = LauncherPrefs.get(mContext).get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS);
+
+ VibrationEffect.Composition composition = VibrationEffect.startComposition();
+ for (int i = 0; i < iterations; i++) {
+ float t = i / (iterations - 1f);
+ float scale = (float) Math.pow((1 - t) * startScale + t * endScale,
+ scaleExponent);
+ composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, scale);
+ }
+
+ vibrate(composition.compose());
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 56a74a9..669aaab 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -89,7 +89,7 @@
import java.util.function.Supplier;
/**
- * Base class for all instrumentation tests providing various utility methods.
+ * Base class for all instrumentation tests providing various utility methods. RUN 4
*/
public abstract class AbstractLauncherUiTest {
@@ -252,6 +252,12 @@
public void setUp() throws Exception {
mLauncher.onTestStart();
+ if (TestStabilityRule.isPresubmit()) {
+ aggressivelyUnlockSysUi();
+ } else {
+ verifyKeyguardInvisible();
+ }
+
final String launcherPackageName = mDevice.getLauncherPackageName();
try {
final Context context = InstrumentationRegistry.getContext();
@@ -285,7 +291,27 @@
verifyKeyguardInvisible();
}
- /** Fail if lock screen is present */
+ private boolean hasSystemUiObject(String resId) {
+ return mDevice.hasObject(By.res(SYSTEMUI_PACKAGE, resId));
+ }
+
+ // Seeing if this will decrease: b/303755862
+ void aggressivelyUnlockSysUi() {
+ for (int i = 0; i < 10 && hasSystemUiObject("keyguard_status_view"); ++i) {
+ Log.d(TAG, "Before attempting to unlock the phone");
+ try {
+ mDevice.executeShellCommand("input keyevent 82");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ mDevice.waitForIdle();
+ }
+ Assert.assertTrue("Keyguard still visible",
+ TestHelpers.wait(
+ Until.gone(By.res(SYSTEMUI_PACKAGE, "keyguard_status_view")), 60000));
+ Log.d(TAG, "Keyguard is not visible");
+ }
+
public static void verifyKeyguardInvisible() {
final boolean keyguardAlreadyVisible = sSeenKeyguard;
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index b8ca43f..d94e4a5 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -1,7 +1,5 @@
package com.android.launcher3.ui;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
-
import android.util.Log;
import android.view.Surface;
@@ -38,7 +36,7 @@
// If running in presubmit, don't run in both orientations.
// It's important to keep presubmits fast even if we will occasionally miss
// regressions in presubmit.
- || TestStabilityRule.getRunFlavor() == PLATFORM_PRESUBMIT) {
+ || TestStabilityRule.isPresubmit()) {
return base;
}
diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
index 38de071..b51045f 100644
--- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
@@ -146,4 +146,8 @@
return sRunFlavor;
}
+
+ public static boolean isPresubmit() {
+ return getRunFlavor() == PLATFORM_PRESUBMIT;
+ }
}