Merge "Update for stashed taskbar animation" into tm-qpr-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 50f1236..5a58bc2 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -272,8 +272,6 @@
<dimen name="taskbar_stashed_small_screen">108dp</dimen>
<dimen name="taskbar_unstash_input_area">316dp</dimen>
<dimen name="taskbar_stashed_handle_height">4dp</dimen>
- <dimen name="taskbar_edu_wave_anim_trans_y">25dp</dimen>
- <dimen name="taskbar_edu_wave_anim_trans_y_return_overshoot">4dp</dimen>
<dimen name="taskbar_edu_horizontal_margin">112dp</dimen>
<dimen name="taskbar_nav_buttons_width_kids">88dp</dimen>
<dimen name="taskbar_nav_buttons_height_kids">40dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 7cf8201..c65fa5f 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -19,6 +19,8 @@
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Rect;
@@ -115,13 +117,19 @@
PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
RectF startingTaskRect = new RectF();
- FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
- source.view, null /* thumbnail */,
- source.drawable, startingTaskRect);
+ final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
+ source.view, null /* thumbnail */, source.drawable, startingTaskRect);
floatingTaskView.setAlpha(1);
floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
false /* fadeWithThumbnail */, true /* isStagedTask */);
controller.setFirstFloatingTaskView(floatingTaskView);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mTarget.getDragLayer().removeView(floatingTaskView);
+ controller.resetState();
+ }
+ });
anim.buildAnim().start();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 0945bf2..8775359 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -42,7 +42,6 @@
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.OnboardingPrefs;
@@ -51,7 +50,6 @@
import com.android.quickstep.views.RecentsView;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.Set;
import java.util.stream.Stream;
@@ -256,11 +254,6 @@
mTaskbarOverrideBackgroundAlpha.updateValue(forceHide ? 0 : 1);
}
- @Override
- public Stream<ItemInfoWithIcon> getAppIconsForEdu() {
- return Arrays.stream(mLauncher.getAppsView().getAppsStore().getApps());
- }
-
/**
* Starts the taskbar education flow, if the user hasn't seen it yet.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 875327d..2435236 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -210,7 +210,7 @@
DeviceProfile deviceProfile = mContext.getDeviceProfile();
Resources resources = mContext.getResources();
Point p = !mContext.isUserSetupComplete()
- ? new Point(0, resources.getDimensionPixelSize(R.dimen.taskbar_suw_frame))
+ ? new Point(0, controllers.taskbarActivityContext.getSetupWindowHeight())
: DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, resources,
TaskbarManager.isPhoneMode(deviceProfile));
mNavButtonsView.getLayoutParams().height = p.y;
@@ -691,8 +691,9 @@
(resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2);
navButtonsLayoutParams.setMarginEnd(0);
navButtonsLayoutParams.gravity = Gravity.START;
+ mNavButtonsView.getLayoutParams().height =
+ mControllers.taskbarActivityContext.getSetupWindowHeight();
mNavButtonContainer.setLayoutParams(navButtonsLayoutParams);
- mNavButtonContainer.requestLayout();
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 13ca58d..d9d46d4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -341,6 +341,9 @@
public void onConfigurationChanged(@Config int configChanges) {
mControllers.onConfigurationChanged(configChanges);
+ if (!mIsUserSetupComplete) {
+ setTaskbarWindowHeight(getSetupWindowHeight());
+ }
}
public boolean isThreeButtonNav() {
@@ -673,7 +676,7 @@
}
if (!isUserSetupComplete()) {
- return resources.getDimensionPixelSize(R.dimen.taskbar_suw_frame);
+ return getSetupWindowHeight();
}
if (DisplayController.isTransientTaskbar(this)) {
@@ -685,6 +688,10 @@
return mDeviceProfile.taskbarSize + Math.max(getLeftCornerRadius(), getRightCornerRadius());
}
+ public int getSetupWindowHeight() {
+ return getResources().getDimensionPixelSize(R.dimen.taskbar_suw_frame);
+ }
+
/**
* Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
* window.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
index 365ec75..c53595d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
@@ -15,70 +15,27 @@
*/
package com.android.launcher3.taskbar;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.Keyframe;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
-import android.content.res.Resources;
-import android.text.TextUtils;
-import android.view.View;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_EDU;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import com.android.launcher3.R;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
-import com.android.launcher3.uioverrides.PredictedAppIcon;
+import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import java.io.PrintWriter;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
/** Handles the Taskbar Education flow. */
public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarController {
- private static final long WAVE_ANIM_DELAY = 250;
- private static final long WAVE_ANIM_STAGGER = 50;
- private static final long WAVE_ANIM_EACH_ICON_DURATION = 633;
- private static final long WAVE_ANIM_SLOT_MACHINE_DURATION = 1085;
- // The fraction of each icon's animation at which we reach the top point of the wave.
- private static final float WAVE_ANIM_FRACTION_TOP = 0.4f;
- // The fraction of each icon's animation at which we reach the bottom, before overshooting.
- private static final float WAVE_ANIM_FRACTION_BOTTOM = 0.9f;
- private static final TimeInterpolator WAVE_ANIM_TO_TOP_INTERPOLATOR = FAST_OUT_SLOW_IN;
- private static final TimeInterpolator WAVE_ANIM_TO_BOTTOM_INTERPOLATOR = ACCEL_2;
- private static final TimeInterpolator WAVE_ANIM_OVERSHOOT_INTERPOLATOR = DEACCEL;
- private static final TimeInterpolator WAVE_ANIM_OVERSHOOT_RETURN_INTERPOLATOR = ACCEL_DEACCEL;
- private static final float WAVE_ANIM_ICON_SCALE = 1.2f;
- // How many icons to cycle through in the slot machine (+ the original icon at each end).
- private static final int WAVE_ANIM_SLOT_MACHINE_NUM_ICONS = 3;
-
private final TaskbarActivityContext mActivity;
- private final float mWaveAnimTranslationY;
- private final float mWaveAnimTranslationYReturnOvershoot;
// Initialized in init.
TaskbarControllers mControllers;
private TaskbarEduView mTaskbarEduView;
- private Animator mAnim;
public TaskbarEduController(TaskbarActivityContext activity) {
mActivity = activity;
-
- final Resources resources = activity.getResources();
- mWaveAnimTranslationY = resources.getDimension(R.dimen.taskbar_edu_wave_anim_trans_y);
- mWaveAnimTranslationYReturnOvershoot = resources.getDimension(
- R.dimen.taskbar_edu_wave_anim_trans_y_return_overshoot);
}
public void init(TaskbarControllers controllers) {
@@ -86,115 +43,32 @@
}
void showEdu() {
- mActivity.setTaskbarWindowFullscreen(true);
- mActivity.getDragLayer().post(() -> {
- TaskbarOverlayContext overlayContext =
- mControllers.taskbarOverlayController.requestWindow();
- mTaskbarEduView = (TaskbarEduView) overlayContext.getLayoutInflater().inflate(
- R.layout.taskbar_edu, overlayContext.getDragLayer(), false);
- mTaskbarEduView.init(new TaskbarEduCallbacks());
- mControllers.navbarButtonsViewController.setSlideInViewVisible(true);
- mTaskbarEduView.setOnCloseBeginListener(
- () -> mControllers.navbarButtonsViewController.setSlideInViewVisible(false));
- mTaskbarEduView.addOnCloseListener(() -> mTaskbarEduView = null);
- mTaskbarEduView.show();
- startAnim(createWaveAnim());
+ TaskbarOverlayController overlayController = mControllers.taskbarOverlayController;
+ TaskbarOverlayContext overlayContext = overlayController.requestWindow();
+ mTaskbarEduView = (TaskbarEduView) overlayContext.getLayoutInflater().inflate(
+ R.layout.taskbar_edu, overlayContext.getDragLayer(), false);
+ mTaskbarEduView.init(new TaskbarEduCallbacks());
+ mControllers.navbarButtonsViewController.setSlideInViewVisible(true);
+
+ TaskbarStashController stashController = mControllers.taskbarStashController;
+ stashController.updateStateForFlag(FLAG_STASHED_IN_APP_EDU, true);
+ stashController.applyState(overlayController.getOpenDuration());
+
+ mTaskbarEduView.setOnCloseBeginListener(() -> {
+ mControllers.navbarButtonsViewController.setSlideInViewVisible(false);
+ // Post in case view is closing due to gesture navigation. If a gesture is in progress,
+ // wait to unstash until after the gesture is finished.
+ MAIN_EXECUTOR.post(() -> stashController.resetFlagIfNoGestureInProgress(
+ FLAG_STASHED_IN_APP_EDU));
});
- }
-
- /**
- * Starts the given animation, ending the previous animation first if it's still playing.
- */
- private void startAnim(Animator anim) {
- if (mAnim != null) {
- mAnim.end();
- }
- mAnim = anim;
- mAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mAnim = null;
- }
- });
- mAnim.start();
- }
-
- /**
- * Creates a staggered "wave" animation where each icon translates and scales up in succession.
- */
- private Animator createWaveAnim() {
- AnimatorSet waveAnim = new AnimatorSet();
- View[] icons = mControllers.taskbarViewController.getIconViews();
- for (int i = 0; i < icons.length; i++) {
- View icon = icons[i];
- AnimatorSet iconAnim = new AnimatorSet();
-
- Keyframe[] scaleKeyframes = new Keyframe[] {
- Keyframe.ofFloat(0, 1f),
- Keyframe.ofFloat(WAVE_ANIM_FRACTION_TOP, WAVE_ANIM_ICON_SCALE),
- Keyframe.ofFloat(WAVE_ANIM_FRACTION_BOTTOM, 1f),
- Keyframe.ofFloat(1f, 1f)
- };
- scaleKeyframes[1].setInterpolator(WAVE_ANIM_TO_TOP_INTERPOLATOR);
- scaleKeyframes[2].setInterpolator(WAVE_ANIM_TO_BOTTOM_INTERPOLATOR);
-
- Keyframe[] translationYKeyframes = new Keyframe[] {
- Keyframe.ofFloat(0, 0f),
- Keyframe.ofFloat(WAVE_ANIM_FRACTION_TOP, -mWaveAnimTranslationY),
- Keyframe.ofFloat(WAVE_ANIM_FRACTION_BOTTOM, 0f),
- // Half of the remaining fraction overshoots, then the other half returns to 0.
- Keyframe.ofFloat(
- WAVE_ANIM_FRACTION_BOTTOM + (1 - WAVE_ANIM_FRACTION_BOTTOM) / 2f,
- mWaveAnimTranslationYReturnOvershoot),
- Keyframe.ofFloat(1f, 0f)
- };
- translationYKeyframes[1].setInterpolator(WAVE_ANIM_TO_TOP_INTERPOLATOR);
- translationYKeyframes[2].setInterpolator(WAVE_ANIM_TO_BOTTOM_INTERPOLATOR);
- translationYKeyframes[3].setInterpolator(WAVE_ANIM_OVERSHOOT_INTERPOLATOR);
- translationYKeyframes[4].setInterpolator(WAVE_ANIM_OVERSHOOT_RETURN_INTERPOLATOR);
-
- iconAnim.play(ObjectAnimator.ofPropertyValuesHolder(icon,
- PropertyValuesHolder.ofKeyframe(SCALE_PROPERTY, scaleKeyframes))
- .setDuration(WAVE_ANIM_EACH_ICON_DURATION));
- iconAnim.play(ObjectAnimator.ofPropertyValuesHolder(icon,
- PropertyValuesHolder.ofKeyframe(View.TRANSLATION_Y, translationYKeyframes))
- .setDuration(WAVE_ANIM_EACH_ICON_DURATION));
-
- if (icon instanceof PredictedAppIcon) {
- // Play slot machine animation through random icons from AllAppsList.
- PredictedAppIcon predictedAppIcon = (PredictedAppIcon) icon;
- ItemInfo itemInfo = (ItemInfo) icon.getTag();
- List<BitmapInfo> iconsToAnimate = mControllers.uiController.getAppIconsForEdu()
- .filter(appInfo -> !TextUtils.equals(appInfo.title, itemInfo.title))
- .map(appInfo -> appInfo.bitmap)
- .filter(bitmap -> !bitmap.isNullOrLowRes())
- .collect(Collectors.toList());
- // Pick n icons at random.
- Collections.shuffle(iconsToAnimate);
- if (iconsToAnimate.size() > WAVE_ANIM_SLOT_MACHINE_NUM_ICONS) {
- iconsToAnimate = iconsToAnimate.subList(0, WAVE_ANIM_SLOT_MACHINE_NUM_ICONS);
- }
- Animator slotMachineAnim = predictedAppIcon.createSlotMachineAnim(iconsToAnimate);
- if (slotMachineAnim != null) {
- iconAnim.play(slotMachineAnim.setDuration(WAVE_ANIM_SLOT_MACHINE_DURATION));
- }
- }
-
- iconAnim.setStartDelay(WAVE_ANIM_STAGGER * i);
- waveAnim.play(iconAnim);
- }
- waveAnim.setStartDelay(WAVE_ANIM_DELAY);
- return waveAnim;
+ mTaskbarEduView.addOnCloseListener(() -> mTaskbarEduView = null);
+ mTaskbarEduView.show();
}
@Override
public void dumpLogs(String prefix, PrintWriter pw) {
pw.println(prefix + "TaskbarEduController:");
-
pw.println(prefix + "\tisShowingEdu=" + (mTaskbarEduView != null));
- pw.println(prefix + "\tmWaveAnimTranslationY=" + mWaveAnimTranslationY);
- pw.println(prefix + "\tmWaveAnimTranslationYReturnOvershoot="
- + mWaveAnimTranslationYReturnOvershoot);
}
/**
@@ -221,5 +95,13 @@
int getIconLayoutBoundsWidth() {
return mControllers.taskbarViewController.getIconLayoutWidth();
}
+
+ int getOpenDuration() {
+ return mControllers.taskbarOverlayController.getOpenDuration();
+ }
+
+ int getCloseDuration() {
+ return mControllers.taskbarOverlayController.getCloseDuration();
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
index bb87f48..d38c6d1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
@@ -35,9 +35,6 @@
public class TaskbarEduView extends AbstractSlideInView<TaskbarOverlayContext>
implements Insettable {
- private static final int DEFAULT_OPEN_DURATION = 500;
- private static final int DEFAULT_CLOSE_DURATION = 200;
-
private final Rect mInsets = new Rect();
// Initialized in init.
@@ -65,7 +62,7 @@
@Override
protected void handleClose(boolean animate) {
- handleClose(animate, DEFAULT_CLOSE_DURATION);
+ handleClose(animate, mTaskbarEduCallbacks.getCloseDuration());
}
@Override
@@ -161,7 +158,7 @@
mOpenCloseAnimator.setValues(
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
mOpenCloseAnimator.setInterpolator(AGGRESSIVE_EASE);
- mOpenCloseAnimator.setDuration(DEFAULT_OPEN_DURATION).start();
+ mOpenCloseAnimator.setDuration(mTaskbarEduCallbacks.getOpenDuration()).start();
}
void snapToPage(int page) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 32c1972..b388512 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -149,7 +149,8 @@
if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
- } else if (controllers.navbarButtonsViewController.isImeVisible) {
+ } else if (controllers.navbarButtonsViewController.isImeVisible
+ && controllers.taskbarStashController.isStashed()) {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (!controllers.uiController.isTaskbarTouchable) {
// Let touches pass through us.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 722430e..e62e533 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -17,7 +17,6 @@
import static android.view.HapticFeedbackConstants.LONG_PRESS;
-import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
import static com.android.launcher3.taskbar.Utilities.appendFlag;
@@ -80,6 +79,7 @@
public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed
public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 10; // Autohide (transient taskbar).
+ public static final int FLAG_STASHED_IN_APP_EDU = 1 << 11; // EDU is visible.
// If any of these flags are enabled, isInApp should return true.
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
@@ -88,7 +88,7 @@
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
| FLAG_STASHED_IN_SYSUI_STATE | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
| FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS
- | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO;
+ | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO | FLAG_STASHED_IN_APP_EDU;
private static final int FLAGS_STASHED_IN_APP_IGNORING_IME =
FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME;
@@ -98,7 +98,8 @@
// Currently any flag that causes us to stash in an app is included, except for IME or All Apps
// since those cover the underlying app anyway and thus the app shouldn't change insets.
private static final int FLAGS_REPORT_STASHED_INSETS_TO_APP = FLAGS_STASHED_IN_APP
- & ~FLAG_STASHED_IN_APP_IME & ~FLAG_STASHED_IN_TASKBAR_ALL_APPS;
+ & ~FLAG_STASHED_IN_APP_IME & ~FLAG_STASHED_IN_TASKBAR_ALL_APPS
+ & ~FLAG_STASHED_IN_APP_EDU;
/**
* How long to stash/unstash when manually invoked via long press.
@@ -374,11 +375,11 @@
if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
DeviceProfile dp = mActivity.getDeviceProfile();
- if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent && !dp.isLandscape) {
+ if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent) {
// We always show the back button in SUW but in portrait the SUW layout may not
- // be wide enough to support overlapping the nav bar with its content. For now,
- // just inset by the bar height.
- return mUnstashedHeight;
+ // be wide enough to support overlapping the nav bar with its content.
+ // We're sending different res values in portrait vs landscape
+ return mActivity.getResources().getDimensionPixelSize(R.dimen.taskbar_suw_insets);
}
boolean isAnimating = mAnimator != null && mAnimator.isStarted();
if (!mControllers.stashedHandleViewController.isStashedHandleVisible()
@@ -392,10 +393,6 @@
return mStashedHeight;
}
- if (!mActivity.isUserSetupComplete()) {
- // Special insets for SUW.
- return mActivity.getResources().getDimensionPixelSize(R.dimen.taskbar_suw_insets);
- }
return mUnstashedHeight;
}
@@ -706,34 +703,27 @@
// Only update the following flags when system gesture is not in progress.
boolean shouldStashForIme = shouldStashForIme();
- maybeResetStashedInAppAllApps(
- hasAnyFlag(FLAG_STASHED_IN_APP_IME) == shouldStashForIme);
+ updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false);
+ updateStateForFlag(FLAG_STASHED_IN_APP_EDU, false);
if (hasAnyFlag(FLAG_STASHED_IN_APP_IME) != shouldStashForIme) {
updateStateForFlag(FLAG_STASHED_IN_APP_IME, shouldStashForIme);
applyState(TASKBAR_STASH_DURATION_FOR_IME, getTaskbarStashStartDelayForIme());
+ } else {
+ applyState(mControllers.taskbarOverlayController.getCloseDuration());
}
}
/**
- * Reset stashed in all apps only if no system gesture is in progress.
+ * Resets the flag if no system gesture is in progress.
* <p>
* Otherwise, the reset should be deferred until after the gesture is finished.
*
* @see #setSystemGestureInProgress
*/
- public void maybeResetStashedInAppAllApps() {
- maybeResetStashedInAppAllApps(true);
- }
-
- private void maybeResetStashedInAppAllApps(boolean applyState) {
- if (mIsSystemGestureInProgress) {
- return;
- }
-
- updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false);
- if (applyState) {
- applyState(ALL_APPS.getTransitionDuration(
- mControllers.taskbarActivityContext, false /* isToState */));
+ public void resetFlagIfNoGestureInProgress(int flag) {
+ if (!mIsSystemGestureInProgress) {
+ updateStateForFlag(flag, false);
+ applyState(mControllers.taskbarOverlayController.getCloseDuration());
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 4ec9b41..6c6b002 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -29,7 +29,6 @@
import com.android.quickstep.views.TaskView;
import java.io.PrintWriter;
-import java.util.stream.Stream;
/**
* Base class for providing different taskbar UI
@@ -66,10 +65,6 @@
protected void onStashedInAppChanged() { }
- public Stream<ItemInfoWithIcon> getAppIconsForEdu() {
- return Stream.empty();
- }
-
/** Called when an icon is launched. */
public void onTaskbarIconLaunched(ItemInfo item) { }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 9936d27..b5e6fac 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -193,7 +193,8 @@
* Should be called when the IME visibility changes, so we can make Taskbar not steal touches.
*/
public void setImeIsVisible(boolean isImeVisible) {
- mTaskbarView.setTouchesEnabled(!isImeVisible);
+ mTaskbarView.setTouchesEnabled(!isImeVisible
+ || DisplayController.isTransientTaskbar(mActivity));
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index c8bfc2a..8502752 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.taskbar.allapps;
-import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import android.animation.PropertyValuesHolder;
@@ -28,6 +27,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsViewController.TaskbarAllAppsCallbacks;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
import com.android.launcher3.views.AbstractSlideInView;
@@ -37,6 +37,9 @@
private TaskbarAllAppsContainerView mAppsView;
private float mShiftRange;
+ // Initialized in init.
+ private TaskbarAllAppsCallbacks mAllAppsCallbacks;
+
public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -46,6 +49,10 @@
super(context, attrs, defStyleAttr);
}
+ void init(TaskbarAllAppsCallbacks callbacks) {
+ mAllAppsCallbacks = callbacks;
+ }
+
/** Opens the all apps view. */
void show(boolean animate) {
if (mIsOpen || mOpenCloseAnimator.isRunning()) {
@@ -58,8 +65,7 @@
mOpenCloseAnimator.setValues(
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
mOpenCloseAnimator.setInterpolator(EMPHASIZED);
- mOpenCloseAnimator.setDuration(
- ALL_APPS.getTransitionDuration(mActivityContext, true /* isToState */)).start();
+ mOpenCloseAnimator.setDuration(mAllAppsCallbacks.getOpenDuration()).start();
} else {
mTranslationShift = TRANSLATION_SHIFT_OPENED;
}
@@ -72,8 +78,7 @@
@Override
protected void handleClose(boolean animate) {
- handleClose(animate,
- ALL_APPS.getTransitionDuration(mActivityContext, false /* isToState */));
+ handleClose(animate, mAllAppsCallbacks.getCloseDuration());
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
index 54392b2..4165486 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_TASKBAR_ALL_APPS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import com.android.launcher3.AbstractFloatingView;
@@ -26,6 +27,7 @@
import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
/**
* Handles the {@link TaskbarAllAppsContainerView} behavior and synchronizes its transitions with
@@ -38,6 +40,7 @@
private final TaskbarAllAppsContainerView mAppsView;
private final TaskbarStashController mTaskbarStashController;
private final NavbarButtonsViewController mNavbarButtonsViewController;
+ private final TaskbarOverlayController mOverlayController;
TaskbarAllAppsViewController(
TaskbarOverlayContext context,
@@ -49,7 +52,9 @@
mAppsView = mSlideInView.getAppsView();
mTaskbarStashController = taskbarControllers.taskbarStashController;
mNavbarButtonsViewController = taskbarControllers.navbarButtonsViewController;
+ mOverlayController = taskbarControllers.taskbarOverlayController;
+ mSlideInView.init(new TaskbarAllAppsCallbacks());
setUpIconLongClick();
setUpAppDivider();
setUpTaskbarStashing();
@@ -93,7 +98,18 @@
mContext, AbstractFloatingView.TYPE_ACTION_POPUP);
// Post in case view is closing due to gesture navigation. If a gesture is in progress,
// wait to unstash until after the gesture is finished.
- mSlideInView.post(mTaskbarStashController::maybeResetStashedInAppAllApps);
+ MAIN_EXECUTOR.post(() -> mTaskbarStashController.resetFlagIfNoGestureInProgress(
+ FLAG_STASHED_IN_TASKBAR_ALL_APPS));
});
}
+
+ class TaskbarAllAppsCallbacks {
+ int getOpenDuration() {
+ return mOverlayController.getOpenDuration();
+ }
+
+ int getCloseDuration() {
+ return mOverlayController.getCloseDuration();
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
index 019e5a6..476e0a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -150,6 +151,16 @@
});
}
+ /** The default open duration for overlays. */
+ public int getOpenDuration() {
+ return ALL_APPS.getTransitionDuration(mTaskbarContext, true);
+ }
+
+ /** The default close duration for overlays. */
+ public int getCloseDuration() {
+ return ALL_APPS.getTransitionDuration(mTaskbarContext, false);
+ }
+
@SuppressLint("WrongConstant")
private LayoutParams createLayoutParams() {
LayoutParams layoutParams = new LayoutParams(
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index dc60875..7c05a10 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -249,12 +249,13 @@
private BitmapInfo getBitmapInfo(Drawable drawable, int userId,
int primaryColor, boolean isInstantApp) {
try (BaseIconFactory bif = getIconFactory()) {
- bif.disableColorExtraction();
bif.setWrapperBackgroundColor(primaryColor);
// User version code O, so that the icon is always wrapped in an adaptive icon container
return bif.createBadgedIconBitmap(drawable,
- new IconOptions().setUser(UserHandle.of(userId)).setInstantApp(isInstantApp));
+ new IconOptions().setUser(UserHandle.of(userId))
+ .setInstantApp(isInstantApp)
+ .setExtractedColor(0));
}
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 0ef4597..0a155cb 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -342,6 +342,10 @@
return;
}
+ if (mItemInfo == null) {
+ return;
+ }
+
if (mItemInfo.container < 0 || appState == null) {
// Write log on the model thread so that logs do not go out of order
// (for eg: drop comes after drag)
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index e8a4b0a..e5c74dc 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -19,21 +19,39 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.content.Intent;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.view.View;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.quickstep.views.FloatingTaskView;
+import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
/** Handles when the stage split lands on the home screen. */
public class SplitToWorkspaceController {
private final Launcher mLauncher;
+ private final DeviceProfile mDP;
private final SplitSelectStateController mController;
+ private final int mHalfDividerSize;
+
public SplitToWorkspaceController(Launcher launcher, SplitSelectStateController controller) {
mLauncher = launcher;
+ mDP = mLauncher.getDeviceProfile();
mController = controller;
+
+ mHalfDividerSize = mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.multi_window_task_divider_size) / 2;
}
/**
@@ -48,19 +66,74 @@
}
Object tag = view.getTag();
Intent intent;
+ BitmapInfo bitmapInfo;
if (tag instanceof WorkspaceItemInfo) {
final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
intent = workspaceItemInfo.intent;
+ bitmapInfo = workspaceItemInfo.bitmap;
} else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
final com.android.launcher3.model.data.AppInfo appInfo =
(com.android.launcher3.model.data.AppInfo) tag;
intent = appInfo.intent;
+ bitmapInfo = appInfo.bitmap;
} else {
return false;
}
+
mController.setSecondTask(intent);
- mController.launchSplitTasks(aBoolean -> mLauncher.getDragLayer().removeView(
- mController.getFirstFloatingTaskView()));
+
+ boolean isTablet = mLauncher.getDeviceProfile().isTablet;
+ SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
+ PendingAnimation pendingAnimation = new PendingAnimation(timings.getDuration());
+
+ Rect firstTaskStartingBounds = new Rect();
+ Rect firstTaskEndingBounds = new Rect();
+ RectF secondTaskStartingBounds = new RectF();
+ Rect secondTaskEndingBounds = new Rect();
+
+ RecentsView recentsView = mLauncher.getOverviewPanel();
+ recentsView.getPagedOrientationHandler().getFinalSplitPlaceholderBounds(mHalfDividerSize,
+ mDP, mController.getActiveSplitStagePosition(), firstTaskEndingBounds,
+ secondTaskEndingBounds);
+
+ FloatingTaskView firstFloatingTaskView = mController.getFirstFloatingTaskView();
+ firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
+ firstFloatingTaskView.addConfirmAnimation(pendingAnimation,
+ new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
+ false /* fadeWithThumbnail */, true /* isStagedTask */);
+
+ FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher,
+ view, null /* thumbnail */, bitmapInfo.newIcon(mLauncher),
+ secondTaskStartingBounds);
+ secondFloatingTaskView.setAlpha(1);
+ secondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
+ secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
+
+ pendingAnimation.addListener(new AnimatorListenerAdapter() {
+ private boolean mIsCancelled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mIsCancelled = true;
+ cleanUp();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mIsCancelled) {
+ mController.launchSplitTasks(aBoolean -> cleanUp());
+ InteractionJankMonitorWrapper.end(
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+ }
+ }
+
+ private void cleanUp() {
+ mLauncher.getDragLayer().removeView(firstFloatingTaskView);
+ mLauncher.getDragLayer().removeView(secondFloatingTaskView);
+ mController.resetState();
+ }
+ });
+ pendingAnimation.buildAnim().start();
return true;
}
}
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index d0d82d4..f8a871a 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -25,34 +25,5 @@
android:focusable="false"
android:saveEnabled="false">
- <include
- layout="@layout/all_apps_bottom_sheet_background"
- android:visibility="gone" />
-
- <include
- layout="@layout/search_results_rv_layout"
- android:visibility="gone" />
-
- <include
- layout="@layout/all_apps_rv_layout"
- android:visibility="gone" />
-
- <com.android.launcher3.allapps.FloatingHeaderView
- android:id="@+id/all_apps_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipToPadding="false"
- android:paddingTop="@dimen/all_apps_header_top_padding"
- android:paddingBottom="@dimen/all_apps_header_bottom_padding"
- android:orientation="vertical" >
-
- <include layout="@layout/floating_header_content" />
-
- <include layout="@layout/all_apps_personal_work_tabs" />
-
- </com.android.launcher3.allapps.FloatingHeaderView>
-
- <include layout="@layout/search_container_all_apps" />
-
- <include layout="@layout/all_apps_fast_scroller" />
+ <include layout="@layout/all_apps_content" />
</com.android.launcher3.allapps.LauncherAllAppsContainerView>
\ No newline at end of file
diff --git a/res/layout/all_apps_content.xml b/res/layout/all_apps_content.xml
new file mode 100644
index 0000000..b33029f
--- /dev/null
+++ b/res/layout/all_apps_content.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2022 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.
+-->
+<!-- This file is used by multiple all_apps.xml. Layout consists of all contents
+ showed in all apps screen
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <include
+ layout="@layout/all_apps_bottom_sheet_background"
+ android:visibility="gone" />
+
+ <include
+ layout="@layout/search_results_rv_layout"
+ android:visibility="gone" />
+
+ <include
+ layout="@layout/all_apps_rv_layout"
+ android:visibility="gone" />
+
+ <com.android.launcher3.allapps.FloatingHeaderView
+ android:id="@+id/all_apps_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipToPadding="false"
+ android:paddingTop="@dimen/all_apps_header_top_padding"
+ android:paddingBottom="@dimen/all_apps_header_bottom_padding"
+ android:orientation="vertical" >
+
+ <include layout="@layout/floating_header_content" />
+
+ <include layout="@layout/all_apps_personal_work_tabs" />
+
+ </com.android.launcher3.allapps.FloatingHeaderView>
+
+ <include layout="@layout/search_container_all_apps" />
+
+ <include layout="@layout/all_apps_fast_scroller" />
+
+</merge>
\ No newline at end of file
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index 11f2020..c59f25d 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.SHOW;
import android.content.Context;
+import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.DragEvent;
@@ -27,12 +28,17 @@
import com.android.launcher3.views.ActivityContext;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* The edit text that reports back when the back key has been pressed.
* Note: AppCompatEditText doesn't fully support #displayCompletions and #onCommitCompletion
*/
public class ExtendedEditText extends EditText {
+ private final Set<OnFocusChangeListener> mOnFocusChangeListeners = new HashSet<>();
+
private boolean mForceDisableSuggestions = false;
/**
@@ -129,4 +135,28 @@
setText("");
}
}
+
+ /**
+ * This method should be preferred to {@link #setOnFocusChangeListener(OnFocusChangeListener)},
+ * as it allows for multiple listeners from different sources.
+ */
+ public void addOnFocusChangeListener(OnFocusChangeListener listener) {
+ mOnFocusChangeListeners.add(listener);
+ }
+
+ /**
+ * Removes the given listener from the set of registered focus listeners, or does nothing if it
+ * wasn't registered in the first place.
+ */
+ public void removeOnFocusChangeListener(OnFocusChangeListener listener) {
+ mOnFocusChangeListeners.remove(listener);
+ }
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+ for (OnFocusChangeListener listener : mOnFocusChangeListeners) {
+ listener.onFocusChange(this, focused);
+ }
+ }
}
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 4d58eb0..4427a49 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -67,7 +67,7 @@
mInput.addTextChangedListener(this);
mInput.setOnEditorActionListener(this);
mInput.setOnBackKeyListener(this);
- mInput.setOnFocusChangeListener(this);
+ mInput.addOnFocusChangeListener(this);
mSearchAlgorithm = searchAlgorithm;
}
@@ -153,6 +153,7 @@
mCallback.clearSearchResult();
mInput.reset();
mQuery = null;
+ mInput.removeOnFocusChangeListener(this);
}
/**
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 669159f..88654b7 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -124,6 +124,10 @@
"FOLDER_NAME_MAJORITY_RANKING", true,
"Suggests folder names based on majority based ranking.");
+ public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = new DeviceFlag(
+ "INJECT_FALLBACK_APP_CORPUS_RESULTS", false, "Inject "
+ + "fallback app corpus result when AiAi fails to return it.");
+
public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
@@ -297,10 +301,6 @@
"USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", false,
"Use local overrides for search request timeout");
- public static final BooleanFlag ENABLE_RICH_ANSWER = new DeviceFlag(
- "ENABLE_RICH_ANSWER", false,
- "Enable rich answer new UI for web answer search results");
-
public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(
"CONTINUOUS_VIEW_TREE_CAPTURE", false, "Capture View tree every frame");
@@ -330,6 +330,10 @@
"HOME_GARDENING_WORKSPACE_BUTTONS", false,
"Change workspace edit buttons to reflect home gardening");
+ public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getDebugFlag(
+ "ENABLE_DOWNLOAD_APP_UX_V2", false, "Updates the download app UX"
+ + " to have better visuals");
+
public static final BooleanFlag ENABLE_TASKBAR_REVISED_THRESHOLDS = getDebugFlag(
"ENABLE_TASKBAR_REVISED_THRESHOLDS", false,
"Uses revised thresholds for transient taskbar.");
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 99822da..94eea35 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -282,7 +282,6 @@
mFolderName = findViewById(R.id.folder_name);
mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
mFolderName.setOnBackKeyListener(this);
- mFolderName.setOnFocusChangeListener(this);
mFolderName.setOnEditorActionListener(this);
mFolderName.setSelectAllOnFocus(true);
mFolderName.setInputType(mFolderName.getInputType()
@@ -457,6 +456,13 @@
// the folder itself.
requestFocus();
super.onAttachedToWindow();
+ mFolderName.addOnFocusChangeListener(this);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mFolderName.removeOnFocusChangeListener(this);
}
@Override
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
index 9a86ede..bb7248f 100644
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
@@ -32,6 +32,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.icons.BaseIconFactory.IconOptions;
import com.android.launcher3.icons.cache.CachingLogic;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Themes;
@@ -76,9 +77,8 @@
Drawable unbadgedDrawable = ShortcutCachingLogic.getIcon(
context, info, LauncherAppState.getIDP(context).fillResIconDpi);
if (unbadgedDrawable == null) return BitmapInfo.LOW_RES_INFO;
- return new BitmapInfo(
- li.createScaledBitmap(unbadgedDrawable, BaseIconFactory.MODE_WITH_SHADOW),
- Themes.getColorAccent(context));
+ return li.createBadgedIconBitmap(unbadgedDrawable,
+ new IconOptions().setExtractedColor(Themes.getColorAccent(context)));
}
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index b4be061..098cf80 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -28,6 +28,7 @@
import android.app.AlertDialog;
import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -315,10 +316,16 @@
*/
public static void onClickSearchAction(Launcher launcher, SearchActionItemInfo itemInfo) {
if (itemInfo.getIntent() != null) {
- if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
- launcher.startActivityForResult(itemInfo.getIntent(), 0);
- } else {
- launcher.startActivity(itemInfo.getIntent());
+ try {
+ if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+ launcher.startActivityForResult(itemInfo.getIntent(), 0);
+ } else {
+ launcher.startActivity(itemInfo.getIntent());
+ }
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(launcher,
+ launcher.getResources().getText(R.string.shortcut_not_available),
+ Toast.LENGTH_SHORT).show();
}
} else if (itemInfo.getPendingIntent() != null) {
try {
diff --git a/tests/res/xml/shortcuts.xml b/tests/res/xml/shortcuts.xml
index bdc22f9..fde0dbb 100644
--- a/tests/res/xml/shortcuts.xml
+++ b/tests/res/xml/shortcuts.xml
@@ -2,6 +2,7 @@
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
<shortcut
android:shortcutId="shortcut1"
+ android:icon="@drawable/test_theme_icon"
android:shortcutShortLabel="@string/shortcut1">
<intent android:action="com.android.launcher3.intent.action.test_shortcut"/>
</shortcut>
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index e66810c..93329fa 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -32,8 +32,11 @@
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.tapl.HomeAllApps;
import com.android.launcher3.tapl.HomeAppIcon;
+import com.android.launcher3.tapl.HomeAppIconMenuItem;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import org.junit.Test;
@@ -49,6 +52,8 @@
public class ThemeIconsTest extends AbstractLauncherUiTest {
private static final String APP_NAME = "ThemeIconTestActivity";
+ private static final String SHORTCUT_APP_NAME = "LauncherTestApp";
+ private static final String SHORTCUT_NAME = "Shortcut 1";
@Test
public void testIconWithoutTheme() throws Exception {
@@ -60,9 +65,28 @@
try {
HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
- executeOnLauncher(l -> verifyIconTheme(l.getAppsView(), false));
+ executeOnLauncher(l -> verifyIconTheme(APP_NAME, l.getAppsView(), false));
icon.dragToWorkspace(false, false);
- executeOnLauncher(l -> verifyIconTheme(l.getWorkspace(), false));
+ executeOnLauncher(l -> verifyIconTheme(APP_NAME, l.getWorkspace(), false));
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+
+ @Test
+ public void testShortcutIconWithoutTheme() throws Exception {
+ setThemeEnabled(false);
+ TaplTestsLauncher3.initialize(this);
+
+ HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+
+ try {
+ HomeAppIcon icon = allApps.getAppIcon(SHORTCUT_APP_NAME);
+ HomeAppIconMenuItem shortcutItem =
+ (HomeAppIconMenuItem) icon.openDeepShortcutMenu().getMenuItem(SHORTCUT_NAME);
+ shortcutItem.dragToWorkspace(false, false);
+ executeOnLauncher(l -> verifyIconTheme(SHORTCUT_NAME, l.getWorkspace(), false));
} finally {
allApps.unfreeze();
}
@@ -78,15 +102,42 @@
try {
HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
- executeOnLauncher(l -> verifyIconTheme(l.getAppsView(), false));
+ executeOnLauncher(l -> verifyIconTheme(APP_NAME, l.getAppsView(), false));
icon.dragToWorkspace(false, false);
- executeOnLauncher(l -> verifyIconTheme(l.getWorkspace(), true));
+ executeOnLauncher(l -> verifyIconTheme(APP_NAME, l.getWorkspace(), true));
} finally {
allApps.unfreeze();
}
}
- private void verifyIconTheme(ViewGroup parent, boolean isThemed) {
+ @Test
+ @ScreenRecord // b/260722220
+ public void testShortcutIconWithTheme() throws Exception {
+ setThemeEnabled(true);
+ TaplTestsLauncher3.initialize(this);
+
+ HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+
+ try {
+ HomeAppIcon icon = allApps.getAppIcon(SHORTCUT_APP_NAME);
+ HomeAppIconMenuItem shortcutItem =
+ (HomeAppIconMenuItem) icon.openDeepShortcutMenu().getMenuItem(SHORTCUT_NAME);
+ shortcutItem.dragToWorkspace(false, false);
+ executeOnLauncher(l -> verifyIconTheme(SHORTCUT_NAME, l.getWorkspace(), true));
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+
+ private void verifyIconTheme(String title, ViewGroup parent, boolean isThemed) {
+ // Wait for Launcher model to be completed
+ try {
+ Executors.MODEL_EXECUTOR.submit(() -> { }).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
// Find the app icon
Queue<View> viewQueue = new ArrayDeque<>();
viewQueue.add(parent);
@@ -100,7 +151,7 @@
}
} else if (view instanceof BubbleTextView) {
BubbleTextView btv = (BubbleTextView) view;
- if (APP_NAME.equals(btv.getText())) {
+ if (title.equals(btv.getText())) {
icon = btv;
break;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index ddeeac2..bddb593 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -20,6 +20,8 @@
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiObject2;
+import java.util.ArrayList;
+
/**
* Operations on search result page opened from home screen qsb.
*/
@@ -27,6 +29,9 @@
// The input resource id in the search box.
private static final String INPUT_RES = "input";
private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background";
+
+ // This particular ID change should happen with caution
+ private static final String SEARCH_CONTAINER_RES_ID = "search_results_list_view";
private final LauncherInstrumentation mLauncher;
SearchResultFromQsb(LauncherInstrumentation launcher) {
@@ -49,6 +54,33 @@
return new AllAppsAppIcon(mLauncher, icon);
}
+ /** Find the web suggestion from search suggestion's title text */
+ public void findWebSuggest(String text) {
+ ArrayList<UiObject2> goldenGateResults =
+ new ArrayList<>(mLauncher.waitForObjectsInContainer(
+ mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),
+ By.clazz(TextView.class)));
+ boolean found = false;
+ for(UiObject2 uiObject: goldenGateResults) {
+ String currentString = uiObject.getText();
+ if (currentString.equals(text)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ throw new IllegalStateException("Web suggestion title: " + text + " not found");
+ }
+ }
+
+ /** Find the total amount of views being displayed and return the size */
+ public int getSearchResultItemSize() {
+ ArrayList<UiObject2> searchResultItems =
+ new ArrayList<>(mLauncher.waitForObjectsInContainer(
+ mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),
+ By.clazz(TextView.class)));
+ return searchResultItems.size();
+ }
+
/**
* Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only.
* @param tapRight Tap on the right of bottom sheet if true, or left otherwise.