Merge "Update gesture nav tutorial with updated phone landscape layouts" into tm-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index de67689..2b71768 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -259,6 +259,7 @@
<dimen name="taskbar_contextual_buttons_size">35dp</dimen>
<dimen name="taskbar_stashed_size">24dp</dimen>
<dimen name="taskbar_stashed_handle_width">220dp</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>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 803dee4..8f8ac8e 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1186,6 +1186,19 @@
return false;
}
+ private boolean hasMultipleTargetsWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
+ int numTargets = 0;
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == mode) {
+ numTargets++;
+ }
+ if (numTargets > 1) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* @return Runner that plays when user goes to Launcher
* ie. pressing home, swiping up from nav bar.
@@ -1580,7 +1593,8 @@
View launcherView = findLauncherView(appTargets);
boolean playFallBackAnimation = (launcherView == null
&& launcherIsForceInvisibleOrOpening)
- || mLauncher.getWorkspace().isOverlayShown();
+ || mLauncher.getWorkspace().isOverlayShown()
+ || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index e949b23..5387b1a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -49,6 +49,7 @@
import android.view.RoundedCorner;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import android.widget.Toast;
@@ -185,8 +186,8 @@
new TaskbarDragLayerController(this, mDragLayer),
new TaskbarViewController(this, taskbarView),
new TaskbarScrimViewController(this, taskbarScrimView),
- new TaskbarUnfoldAnimationController(unfoldTransitionProgressProvider,
- mWindowManager),
+ new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
+ mWindowManager, WindowManagerGlobal.getWindowManagerService()),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index cc462c1..5ce4fa7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -42,6 +42,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.SettingsCache;
@@ -74,8 +75,11 @@
private final SimpleBroadcastReceiver mShutdownReceiver;
// The source for this provider is set when Launcher is available
+ // We use 'non-destroyable' version here so the original provider won't be destroyed
+ // as it is tied to the activity lifecycle, not the taskbar lifecycle.
+ // It's destruction/creation will be managed by the activity.
private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
- new ScopedUnfoldTransitionProgressProvider();
+ new NonDestroyableScopedUnfoldTransitionProgressProvider();
private TaskbarActivityContext mTaskbarActivityContext;
private StatefulActivity mActivity;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
index d5ea570..64a4fa7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
@@ -15,12 +15,14 @@
*/
package com.android.launcher3.taskbar;
+import android.view.IWindowManager;
import android.view.View;
import android.view.WindowManager;
import com.android.quickstep.util.LauncherViewsMoveFromCenterTranslationApplier;
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
@@ -31,14 +33,18 @@
public class TaskbarUnfoldAnimationController implements
TaskbarControllers.LoggableTaskbarController {
- private final ScopedUnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
+ private final ScopedUnfoldTransitionProgressProvider mScopedUnfoldTransitionProgressProvider;
+ private final NaturalRotationUnfoldProgressProvider mNaturalUnfoldTransitionProgressProvider;
private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimator;
private final TransitionListener mTransitionListener = new TransitionListener();
private TaskbarViewController mTaskbarViewController;
- public TaskbarUnfoldAnimationController(ScopedUnfoldTransitionProgressProvider
- unfoldTransitionProgressProvider, WindowManager windowManager) {
- mUnfoldTransitionProgressProvider = unfoldTransitionProgressProvider;
+ public TaskbarUnfoldAnimationController(BaseTaskbarContext context,
+ ScopedUnfoldTransitionProgressProvider source,
+ WindowManager windowManager, IWindowManager iWindowManager) {
+ mScopedUnfoldTransitionProgressProvider = source;
+ mNaturalUnfoldTransitionProgressProvider =
+ new NaturalRotationUnfoldProgressProvider(context, iWindowManager, source);
mMoveFromCenterAnimator = new UnfoldMoveFromCenterAnimator(windowManager,
new LauncherViewsMoveFromCenterTranslationApplier());
}
@@ -48,18 +54,21 @@
* @param taskbarControllers references to all other taskbar controllers
*/
public void init(TaskbarControllers taskbarControllers) {
+ mNaturalUnfoldTransitionProgressProvider.init();
mTaskbarViewController = taskbarControllers.taskbarViewController;
mTaskbarViewController.addOneTimePreDrawListener(() ->
- mUnfoldTransitionProgressProvider.setReadyToHandleTransition(true));
- mUnfoldTransitionProgressProvider.addCallback(mTransitionListener);
+ mScopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(true));
+ mNaturalUnfoldTransitionProgressProvider.addCallback(mTransitionListener);
}
/**
* Destroys the controller
*/
public void onDestroy() {
- mUnfoldTransitionProgressProvider.setReadyToHandleTransition(false);
- mUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
+ mScopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(false);
+ mNaturalUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
+ mNaturalUnfoldTransitionProgressProvider.destroy();
+ mTaskbarViewController = null;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 6e34ee0..a89061b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -20,13 +20,14 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.AnimatedFloat.VALUE;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.FloatProperty;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnPreDrawListener;
+
+import androidx.core.view.OneShotPreDrawListener;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
@@ -143,18 +144,8 @@
* drawing a frame and invoked only once
* @param listener callback that will be invoked before drawing the next frame
*/
- public void addOneTimePreDrawListener(Runnable listener) {
- mTaskbarView.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- final ViewTreeObserver viewTreeObserver = mTaskbarView.getViewTreeObserver();
- if (viewTreeObserver.isAlive()) {
- listener.run();
- viewTreeObserver.removeOnPreDrawListener(this);
- }
- return true;
- }
- });
+ public void addOneTimePreDrawListener(@NonNull Runnable listener) {
+ OneShotPreDrawListener.add(mTaskbarView, listener);
}
public Rect getIconLayoutBounds() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/unfold/NonDestroyableScopedUnfoldTransitionProgressProvider.java b/quickstep/src/com/android/launcher3/taskbar/unfold/NonDestroyableScopedUnfoldTransitionProgressProvider.java
new file mode 100644
index 0000000..f9da4e4
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/unfold/NonDestroyableScopedUnfoldTransitionProgressProvider.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+package com.android.launcher3.taskbar.unfold;
+
+import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+
+/**
+ * ScopedUnfoldTransitionProgressProvider that doesn't propagate destroy method
+ */
+public class NonDestroyableScopedUnfoldTransitionProgressProvider extends
+ ScopedUnfoldTransitionProgressProvider {
+
+ @Override
+ public void destroy() {
+ // no-op
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 783c868..57b42f8 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -49,9 +49,9 @@
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
public static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.debug.shell_transit", false);
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
- && SystemProperties.getBoolean("persist.debug.shell_transit_rotate", false);
+ && SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
private RecentsAnimationController mController;
private RecentsAnimationCallbacks mCallbacks;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index dbe260a..7836ece 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -22,6 +22,7 @@
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.quickstep.InputConsumer;
@@ -36,14 +37,20 @@
private final GestureDetector mLongPressDetector;
private final float mSquaredTouchSlop;
+
private float mDownX, mDownY;
private boolean mCanceledUnstashHint;
+ private final float mUnstashArea;
+ private final float mScreenWidth;
public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
super(delegate, inputMonitor);
mTaskbarActivityContext = taskbarActivityContext;
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
+ mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
+ mUnstashArea = context.getResources()
+ .getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
@Override
@@ -69,11 +76,13 @@
final float y = ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
- mDownX = x;
- mDownY = y;
- mTaskbarActivityContext.startTaskbarUnstashHint(
- /* animateForward = */ true);
- mCanceledUnstashHint = false;
+ if (isInArea(x)) {
+ mDownX = x;
+ mDownY = y;
+ mTaskbarActivityContext.startTaskbarUnstashHint(
+ /* animateForward = */ true);
+ mCanceledUnstashHint = false;
+ }
break;
case MotionEvent.ACTION_MOVE:
if (!mCanceledUnstashHint
@@ -95,10 +104,18 @@
}
}
+ private boolean isInArea(float x) {
+ float areaFromMiddle = mUnstashArea / 2.0f;
+ float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
+ return distFromMiddle < areaFromMiddle;
+ }
+
private void onLongPressDetected(MotionEvent motionEvent) {
- if (mTaskbarActivityContext != null
- && mTaskbarActivityContext.onLongPressToUnstashTaskbar()) {
- setActive(motionEvent);
+ if (mTaskbarActivityContext != null && isInArea(motionEvent.getRawX())) {
+ boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar();
+ if (taskBarPressed) {
+ setActive(motionEvent);
+ }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index 51a9915..63d5b0d 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -48,10 +48,10 @@
import androidx.core.content.FileProvider;
import com.android.internal.app.ChooserActivity;
+import com.android.internal.util.ScreenshotHelper;
import com.android.launcher3.BuildConfig;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.utilities.BitmapUtil;
import java.io.File;
import java.io.FileOutputStream;
@@ -77,7 +77,8 @@
public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
Rect screenshotBounds,
Insets visibleInsets, Task.TaskKey task) {
- systemUiProxy.handleImageBundleAsScreenshot(BitmapUtil.hardwareBitmapToBundle(screenshot),
+ systemUiProxy.handleImageBundleAsScreenshot(
+ ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(screenshot),
screenshotBounds, visibleInsets, task);
}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index fb7fda1..09f0858 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -36,7 +36,7 @@
*/
public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest {
static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.debug.shell_transit", false);
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
@Override
protected TestRule getRulesInsideActivityMonitor() {
return RuleChain.
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index cd9bbf7..84505d9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -346,9 +346,14 @@
workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
- isQsbInline = isLargeTablet && isLandscape && hotseatQsbHeight > 0;
+ // Whether QSB might be inline in appropriate orientation (landscape).
+ boolean canQsbInline = isLargeTablet && hotseatQsbHeight > 0;
+ isQsbInline = canQsbInline && isLandscape;
- if (isTaskbarPresent && !isGestureMode && isQsbInline) {
+ // We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
+ // might be inline in either orientations, to keep hotseat size consistent across rotation.
+ boolean areNavButtonsInline = isTaskbarPresent && !isGestureMode;
+ if (areNavButtonsInline && canQsbInline) {
numShownHotseatIcons = inv.numShrunkenHotseatIcons;
} else {
numShownHotseatIcons =
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 308a8f2..5ece4a6 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -440,7 +440,7 @@
cn,
sectionKey.first);
}
- if (loadFallbackTitle && TextUtils.isEmpty(entry.title)) {
+ if (loadFallbackTitle && TextUtils.isEmpty(entry.title) && lai != null) {
loadFallbackTitle(
lai,
entry,
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index daa8fb7..6e97774 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -31,6 +31,7 @@
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.SparseArray;
@@ -55,7 +56,9 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.model.UserManagerState;
import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.pm.UserCache;
import com.android.launcher3.views.ArrowTipView;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.SpringRelativeLayout;
@@ -94,13 +97,17 @@
"launcher.widgets_education_dialog_seen";
private final Rect mInsets = new Rect();
+
+ private final UserManagerState mUserManagerState = new UserManagerState();
+
private final boolean mHasWorkProfile;
private final SparseArray<AdapterHolder> mAdapters = new SparseArray();
private final UserHandle mCurrentUser = Process.myUserHandle();
private final Predicate<WidgetsListBaseEntry> mPrimaryWidgetsFilter =
entry -> mCurrentUser.equals(entry.mPkgItem.user);
private final Predicate<WidgetsListBaseEntry> mWorkWidgetsFilter =
- mPrimaryWidgetsFilter.negate();
+ entry -> !mCurrentUser.equals(entry.mPkgItem.user)
+ && !mUserManagerState.isUserQuiet(entry.mPkgItem.user);
@Nullable private ArrowTipView mLatestEducationalTip;
private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
new OnLayoutChangeListener() {
@@ -171,6 +178,9 @@
: 0;
mWidgetSheetContentHorizontalPadding = 2 * resources.getDimensionPixelSize(
R.dimen.widget_cell_horizontal_padding);
+
+ mUserManagerState.init(UserCache.INSTANCE.get(context),
+ context.getSystemService(UserManager.class));
}
public WidgetsFullSheet(Context context, AttributeSet attrs) {
@@ -259,10 +269,15 @@
boolean isWidgetAvailable = adapterHolder.mWidgetsListAdapter.hasVisibleEntries();
adapterHolder.mWidgetsRecyclerView.setVisibility(isWidgetAvailable ? VISIBLE : GONE);
- mNoWidgetsView.setText(
- adapterHolder.mAdapterType == AdapterHolder.SEARCH
- ? R.string.no_search_results
- : R.string.no_widgets_available);
+ if (adapterHolder.mAdapterType == AdapterHolder.SEARCH) {
+ mNoWidgetsView.setText(R.string.no_search_results);
+ } else if (adapterHolder.mAdapterType == AdapterHolder.WORK
+ && mUserManagerState.isAnyProfileQuietModeEnabled()
+ && mActivityContext.getStringCache() != null) {
+ mNoWidgetsView.setText(mActivityContext.getStringCache().workProfilePausedTitle);
+ } else {
+ mNoWidgetsView.setText(R.string.no_widgets_available);
+ }
mNoWidgetsView.setVisibility(isWidgetAvailable ? GONE : VISIBLE);
}