Merge "Show multiple App Info A11y options for split app icons" into sc-v2-dev
diff --git a/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml b/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml
index d6160de..534f241 100644
--- a/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml
+++ b/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml
@@ -16,7 +16,7 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/taskbar_icon_selection_ripple">
+ android:color="@color/taskbar_nav_icon_selection_ripple">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
diff --git a/quickstep/res/layout/taskbar_nav_button.xml b/quickstep/res/layout/taskbar_nav_button.xml
index 4ffb8d8..aea4885 100644
--- a/quickstep/res/layout/taskbar_nav_button.xml
+++ b/quickstep/res/layout/taskbar_nav_button.xml
@@ -15,7 +15,10 @@
-->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/taskbar_nav_buttons_size"
android:layout_height="@dimen/taskbar_nav_buttons_size"
android:background="@drawable/taskbar_icon_click_feedback_roundrect"
- android:scaleType="center"/>
\ No newline at end of file
+ android:scaleType="center"
+ android:tint="@color/taskbar_nav_icon_light_color"
+ tools:ignore="UseAppTint" />
\ No newline at end of file
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index f237d26..671a617 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -25,14 +25,14 @@
<!-- Taskbar -->
<color name="taskbar_background">@color/overview_scrim_dark</color>
- <color name="taskbar_icon_selection_ripple">#E0E0E0</color>
-
+ <color name="taskbar_nav_icon_selection_ripple">#E0E0E0</color>
+ <color name="taskbar_nav_icon_light_color">#ffffff</color>
+ <!-- The dark navigation button color is only used in the rare cases that taskbar isn't drawing
+ its background and the underlying app has requested dark buttons. -->
+ <color name="taskbar_nav_icon_dark_color">#99000000</color>
<color name="taskbar_stashed_handle_light_color">#EBffffff</color>
<color name="taskbar_stashed_handle_dark_color">#99000000</color>
- <color name="rotation_button_light_color">#FFF</color>
- <color name="rotation_button_dark_color">#99000000</color>
-
<!-- Gesture navigation tutorial -->
<color name="gesture_tutorial_back_arrow_color">#FFFFFFFF</color>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 6e2d2a9..38e8e72 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -301,7 +301,8 @@
mActionsView = findViewById(R.id.overview_actions_view);
RecentsView overviewPanel = (RecentsView) getOverviewPanel();
SplitSelectStateController controller =
- new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
+ new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this),
+ getStateManager(), getDepthController());
overviewPanel.init(mActionsView, controller);
mActionsView.setDp(getDeviceProfile());
mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 4b6dacd..0565f7e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -15,11 +15,8 @@
*/
package com.android.launcher3.taskbar;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y_LONG_CLICK;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
@@ -36,11 +33,11 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
+import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.LayoutRes;
-import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Rect;
import android.graphics.Region;
@@ -92,9 +89,8 @@
private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
- private View.OnLongClickListener mA11yLongClickListener;
private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
- private final ArrayList<View> mAllButtons = new ArrayList<>();
+ private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
private int mState;
private final TaskbarActivityContext mContext;
@@ -103,11 +99,17 @@
// Used for IME+A11Y buttons
private final ViewGroup mEndContextualContainer;
private final ViewGroup mStartContextualContainer;
+ private final int mLightIconColor;
+ private final int mDarkIconColor;
private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
this::updateNavButtonTranslationY);
private final AnimatedFloat mNavButtonTranslationYMultiplier = new AnimatedFloat(
this::updateNavButtonTranslationY);
+ private final AnimatedFloat mTaskbarNavButtonDarkIntensity = new AnimatedFloat(
+ this::updateNavButtonDarkIntensity);
+ private final AnimatedFloat mNavButtonDarkIntensityMultiplier = new AnimatedFloat(
+ this::updateNavButtonDarkIntensity);
private final RotationButtonListener mRotationButtonListener = new RotationButtonListener();
private final Rect mFloatingRotationButtonBounds = new Rect();
@@ -125,6 +127,9 @@
mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
mEndContextualContainer = mNavButtonsView.findViewById(R.id.end_contextual_buttons);
mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
+
+ mLightIconColor = context.getColor(R.color.taskbar_nav_icon_light_color);
+ mDarkIconColor = context.getColor(R.color.taskbar_nav_icon_dark_color);
}
/**
@@ -135,11 +140,6 @@
mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
mNavButtonTranslationYMultiplier.value = 1;
- mA11yLongClickListener = view -> {
- mControllers.navButtonController.onButtonClick(BUTTON_A11Y_LONG_CLICK);
- return true;
- };
-
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarViewController.getTaskbarIconAlpha()
.getProperty(ALPHA_INDEX_IME),
@@ -278,7 +278,6 @@
mPropertyHolders.add(new StatePropertyHolder(mA11yButton,
flags -> (flags & FLAG_A11Y_VISIBLE) != 0
&& (flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0));
- mA11yButton.setOnLongClickListener(mA11yLongClickListener);
}
private void parseSystemUiFlags(int sysUiStateFlags) {
@@ -379,6 +378,16 @@
return mTaskbarNavButtonTranslationY;
}
+ /** Use to set the dark intensity for the all nav+contextual buttons */
+ public AnimatedFloat getTaskbarNavButtonDarkIntensity() {
+ return mTaskbarNavButtonDarkIntensity;
+ }
+
+ /** Use to determine whether to use the dark intensity requested by the underlying app */
+ public AnimatedFloat getNavButtonDarkIntensityMultiplier() {
+ return mNavButtonDarkIntensityMultiplier;
+ }
+
/**
* Does not call {@link #applyState()}. Don't forget to!
*/
@@ -402,6 +411,16 @@
* mNavButtonTranslationYMultiplier.value);
}
+ private void updateNavButtonDarkIntensity() {
+ float darkIntensity = mTaskbarNavButtonDarkIntensity.value
+ * mNavButtonDarkIntensityMultiplier.value;
+ int iconColor = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, mLightIconColor,
+ mDarkIconColor);
+ for (ImageView button : mAllButtons) {
+ button.setImageTintList(ColorStateList.valueOf(iconColor));
+ }
+ }
+
private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
return addButton(drawableId, buttonType, parent, navButtonController, id,
@@ -414,6 +433,8 @@
ImageView buttonView = addButton(parent, id, layoutId);
buttonView.setImageResource(drawableId);
buttonView.setOnClickListener(view -> navButtonController.onButtonClick(buttonType));
+ buttonView.setOnLongClickListener(view ->
+ navButtonController.onButtonLongClick(buttonType));
return buttonView;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index cc83431..5354232 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -151,8 +151,8 @@
buttonController,
new NavbarButtonsViewController(this, navButtonsView),
new RotationButtonController(this,
- c.getColor(R.color.rotation_button_light_color),
- c.getColor(R.color.rotation_button_dark_color),
+ c.getColor(R.color.taskbar_nav_icon_light_color),
+ c.getColor(R.color.taskbar_nav_icon_dark_color),
R.drawable.ic_sysbar_rotate_button_ccw_start_0,
R.drawable.ic_sysbar_rotate_button_ccw_start_90,
R.drawable.ic_sysbar_rotate_button_cw_start_0,
@@ -394,6 +394,11 @@
mControllers.rotationButtonController.onBehaviorChanged(displayId, behavior);
}
+ public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
+ mControllers.navbarButtonsViewController.getTaskbarNavButtonDarkIntensity()
+ .updateValue(darkIntensity);
+ }
+
/**
* Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 81039d4..248c40d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -52,6 +52,9 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private AnimatedFloat mNavButtonDarkIntensityMultiplier;
+
+ private float mLastSetBackgroundAlpha;
public TaskbarDragLayerController(TaskbarActivityContext activity,
TaskbarDragLayer taskbarDragLayer) {
@@ -65,6 +68,9 @@
mControllers = controllers;
mTaskbarDragLayer.init(new TaskbarDragLayerCallbacks());
+ mNavButtonDarkIntensityMultiplier = mControllers.navbarButtonsViewController
+ .getNavButtonDarkIntensityMultiplier();
+
mBgTaskbar.value = 1;
mKeyguardBgTaskbar.value = 1;
mNotificationShadeBgTaskbar.value = 1;
@@ -114,13 +120,22 @@
final float bgNavbar = mBgNavbar.value;
final float bgTaskbar = mBgTaskbar.value * mKeyguardBgTaskbar.value
* mNotificationShadeBgTaskbar.value;
- mTaskbarDragLayer.setTaskbarBackgroundAlpha(
- mBgOverride.value * Math.max(bgNavbar, bgTaskbar)
- );
+ mLastSetBackgroundAlpha = mBgOverride.value * Math.max(bgNavbar, bgTaskbar);
+ mTaskbarDragLayer.setTaskbarBackgroundAlpha(mLastSetBackgroundAlpha);
+
+ updateNavBarDarkIntensityMultiplier();
}
private void updateBackgroundOffset() {
mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value);
+
+ updateNavBarDarkIntensityMultiplier();
+ }
+
+ private void updateNavBarDarkIntensityMultiplier() {
+ // Zero out the app-requested dark intensity when we're drawing our own background.
+ float effectiveBgAlpha = mLastSetBackgroundAlpha * (1 - mBgOffset.value);
+ mNavButtonDarkIntensityMultiplier.updateValue(1 - effectiveBgAlpha);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index b2b078c..6b7c597 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -42,7 +42,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.SettingsCache;
@@ -269,6 +268,12 @@
}
}
+ public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
+ if (mTaskbarActivityContext != null) {
+ mTaskbarActivityContext.onNavButtonsDarkIntensityChanged(darkIntensity);
+ }
+ }
+
/**
* Called when the manager is no longer needed
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index a8a0b59..ae23eda 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -16,9 +16,11 @@
package com.android.launcher3.taskbar;
-import static android.view.Display.DEFAULT_DISPLAY;
-import android.view.inputmethod.InputMethodManager;
+import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS;
+import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_KEY;
+
+import android.os.Bundle;
import androidx.annotation.IntDef;
@@ -35,11 +37,9 @@
* Controller for 3 button mode in the taskbar.
* Handles all the functionality of the various buttons, making/routing the right calls into
* launcher or sysui/system.
- *
- * TODO: Create callbacks to hook into UI layer since state will change for more context buttons/
- * assistant invocation.
*/
public class TaskbarNavButtonController {
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
BUTTON_BACK,
@@ -47,7 +47,6 @@
BUTTON_RECENTS,
BUTTON_IME_SWITCH,
BUTTON_A11Y,
- BUTTON_A11Y_LONG_CLICK
})
public @interface TaskbarButton {}
@@ -57,7 +56,6 @@
static final int BUTTON_RECENTS = BUTTON_HOME << 1;
static final int BUTTON_IME_SWITCH = BUTTON_RECENTS << 1;
static final int BUTTON_A11Y = BUTTON_IME_SWITCH << 1;
- static final int BUTTON_A11Y_LONG_CLICK = BUTTON_A11Y << 1;
private final TouchInteractionService mService;
@@ -82,9 +80,22 @@
case BUTTON_A11Y:
notifyImeClick(false /* longClick */);
break;
- case BUTTON_A11Y_LONG_CLICK:
+ }
+ }
+
+ public boolean onButtonLongClick(@TaskbarButton int buttonType) {
+ switch (buttonType) {
+ case BUTTON_HOME:
+ startAssistant();
+ return true;
+ case BUTTON_A11Y:
notifyImeClick(true /* longClick */);
- break;
+ return true;
+ case BUTTON_BACK:
+ case BUTTON_IME_SWITCH:
+ case BUTTON_RECENTS:
+ default:
+ return false;
}
}
@@ -113,4 +124,11 @@
systemUiProxy.notifyAccessibilityButtonClicked(mService.getDisplayId());
}
}
+
+ private void startAssistant() {
+ Bundle args = new Bundle();
+ args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
+ SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
+ systemUiProxy.startAssistant(args);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index acb4aa8..60842c8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -282,6 +282,12 @@
// Just hide/show the icons instead of stashing into a handle.
mAnimator.play(mIconAlphaForStash.animateToValue(isStashed ? 0 : 1)
.setDuration(duration));
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimator = null;
+ }
+ });
return;
}
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index c5f4a53..097850f 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -36,6 +36,7 @@
import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.util.StagedSplitBounds;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
@@ -219,6 +220,26 @@
return newTasks;
}
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "RecentTasksList:");
+ writer.println(prefix + " mChangeId=" + mChangeId);
+ writer.println(prefix + " mResultsUi=[id=" + mResultsUi.mRequestId + ", tasks=");
+ for (GroupTask task : mResultsUi) {
+ writer.println(prefix + " t1=" + task.task1.key.id
+ + " t2=" + (task.hasMultipleTasks() ? task.task2.key.id : "-1"));
+ }
+ writer.println(prefix + " ]");
+ int currentUserId = Process.myUserHandle().getIdentifier();
+ ArrayList<GroupedRecentTaskInfo> rawTasks =
+ mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId);
+ writer.println(prefix + " rawTasks=[");
+ for (GroupedRecentTaskInfo task : rawTasks) {
+ writer.println(prefix + " t1=" + task.mTaskInfo1.taskId
+ + " t2=" + (task.mTaskInfo2 != null ? task.mTaskInfo2.taskId : "-1"));
+ }
+ writer.println(prefix + " ]");
+ }
+
private static class TaskLoadResult extends ArrayList<GroupTask> {
final int mRequestId;
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 09a0b7d..d6efc71 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -128,7 +128,8 @@
SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
SplitSelectStateController controller =
- new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
+ new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this),
+ getStateManager(), null /*depthController*/);
mDragLayer.recreateControllers();
mFallbackRecentsView.init(mActionsView, controller);
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index ac97dd6..5d77a6e 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -24,6 +24,7 @@
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
+import android.content.Intent;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
@@ -42,6 +43,7 @@
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
@@ -176,7 +178,7 @@
@Override
public void onTaskRemoved(int taskId) {
- Task.TaskKey stubKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
+ Task.TaskKey stubKey = new Task.TaskKey(taskId, 0, new Intent(), null, 0, 0);
mThumbnailCache.remove(stubKey);
mIconCache.onTaskRemoved(stubKey);
}
@@ -219,6 +221,11 @@
mThumbnailChangeListeners.remove(listener);
}
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "RecentsModel:");
+ mTaskList.dump(" ", writer);
+ }
+
/**
* Listener for receiving various task properties changes
*/
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 4239739..c8abd14 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -39,7 +39,6 @@
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -52,12 +51,12 @@
import com.android.wm.shell.pip.IPipAnimationListener;
import com.android.wm.shell.recents.IRecentTasks;
import com.android.wm.shell.recents.IRecentTasksListener;
-import com.android.wm.shell.util.GroupedRecentTaskInfo;
import com.android.wm.shell.splitscreen.ISplitScreen;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
import com.android.wm.shell.startingsurface.IStartingWindow;
import com.android.wm.shell.startingsurface.IStartingWindowListener;
import com.android.wm.shell.transition.IShellTransitions;
+import com.android.wm.shell.util.GroupedRecentTaskInfo;
import java.util.ArrayList;
import java.util.Arrays;
@@ -84,14 +83,16 @@
MAIN_EXECUTOR.execute(() -> clearProxy());
};
- // Save the listeners passed into the proxy since when set/register these listeners,
- // setProxy may not have been called, eg. OverviewProxyService is not connected yet.
- private IPipAnimationListener mPendingPipAnimationListener;
- private ISplitScreenListener mPendingSplitScreenListener;
- private IStartingWindowListener mPendingStartingWindowListener;
- private ISmartspaceCallback mPendingSmartspaceCallback;
- private IRecentTasksListener mPendingRecentTasksListener;
- private final ArrayList<RemoteTransitionCompat> mPendingRemoteTransitions = new ArrayList<>();
+ // Save the listeners passed into the proxy since OverviewProxyService may not have been bound
+ // yet, and we'll need to set/register these listeners with SysUI when they do. Note that it is
+ // up to the caller to clear the listeners to prevent leaks as these can be held indefinitely
+ // in case SysUI needs to rebind.
+ private IPipAnimationListener mPipAnimationListener;
+ private ISplitScreenListener mSplitScreenListener;
+ private IStartingWindowListener mStartingWindowListener;
+ private ISmartspaceCallback mSmartspaceCallback;
+ private IRecentTasksListener mRecentTasksListener;
+ private final ArrayList<RemoteTransitionCompat> mRemoteTransitions = new ArrayList<>();
// Used to dedupe calls to SystemUI
private int mLastShelfHeight;
@@ -168,29 +169,23 @@
mRecentTasks = recentTasks;
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
- if (mPendingPipAnimationListener != null && mPip != null) {
- setPinnedStackAnimationListener(mPendingPipAnimationListener);
- mPendingPipAnimationListener = null;
+ if (mPipAnimationListener != null && mPip != null) {
+ setPinnedStackAnimationListener(mPipAnimationListener);
}
- if (mPendingSplitScreenListener != null && mSplitScreen != null) {
- registerSplitScreenListener(mPendingSplitScreenListener);
- mPendingSplitScreenListener = null;
+ if (mSplitScreenListener != null && mSplitScreen != null) {
+ registerSplitScreenListener(mSplitScreenListener);
}
- if (mPendingStartingWindowListener != null && mStartingWindow != null) {
- setStartingWindowListener(mPendingStartingWindowListener);
- mPendingStartingWindowListener = null;
+ if (mStartingWindowListener != null && mStartingWindow != null) {
+ setStartingWindowListener(mStartingWindowListener);
}
- if (mPendingSmartspaceCallback != null && mSmartspaceTransitionController != null) {
- setSmartspaceCallback(mPendingSmartspaceCallback);
- mPendingSmartspaceCallback = null;
+ if (mSmartspaceCallback != null && mSmartspaceTransitionController != null) {
+ setSmartspaceCallback(mSmartspaceCallback);
}
- for (int i = mPendingRemoteTransitions.size() - 1; i >= 0; --i) {
- registerRemoteTransition(mPendingRemoteTransitions.get(i));
+ for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
+ registerRemoteTransition(mRemoteTransitions.get(i));
}
- mPendingRemoteTransitions.clear();
- if (mPendingRecentTasksListener != null && mRecentTasks != null) {
- registerRecentTasksListener(mPendingRecentTasksListener);
- mPendingRecentTasksListener = null;
+ if (mRecentTasksListener != null && mRecentTasks != null) {
+ registerRecentTasksListener(mRecentTasksListener);
}
if (mPendingSetNavButtonAlpha != null) {
@@ -469,8 +464,6 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call handleImageBundleAsScreenshot");
}
- } else if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_SCREENSHOT, "sysuiproxy, no proxy available");
}
}
@@ -516,9 +509,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call setPinnedStackAnimationListener", e);
}
- } else {
- mPendingPipAnimationListener = listener;
}
+ mPipAnimationListener = listener;
}
public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
@@ -556,9 +548,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call registerSplitScreenListener");
}
- } else {
- mPendingSplitScreenListener = listener;
}
+ mSplitScreenListener = listener;
}
public void unregisterSplitScreenListener(ISplitScreenListener listener) {
@@ -569,7 +560,7 @@
Log.w(TAG, "Failed call unregisterSplitScreenListener");
}
}
- mPendingSplitScreenListener = null;
+ mSplitScreenListener = null;
}
/** Start multiple tasks in split-screen simultaneously. */
@@ -690,9 +681,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call registerRemoteTransition");
}
- } else {
- mPendingRemoteTransitions.add(remoteTransition);
}
+ mRemoteTransitions.add(remoteTransition);
}
public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) {
@@ -703,7 +693,7 @@
Log.w(TAG, "Failed call registerRemoteTransition");
}
}
- mPendingRemoteTransitions.remove(remoteTransition);
+ mRemoteTransitions.remove(remoteTransition);
}
//
@@ -720,9 +710,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call setStartingWindowListener", e);
}
- } else {
- mPendingStartingWindowListener = listener;
}
+ mStartingWindowListener = listener;
}
//
@@ -736,9 +725,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call setStartingWindowListener", e);
}
- } else {
- mPendingSmartspaceCallback = callback;
}
+ mSmartspaceCallback = callback;
}
//
@@ -752,9 +740,8 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed call registerRecentTasksListener", e);
}
- } else {
- mPendingRecentTasksListener = listener;
}
+ mRecentTasksListener = listener;
}
public void unregisterRecentTasksListener(IRecentTasksListener listener) {
@@ -765,7 +752,7 @@
Log.w(TAG, "Failed call unregisterRecentTasksListener");
}
}
- mPendingRecentTasksListener = null;
+ mRecentTasksListener = null;
}
public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 6addfe3..e77ec78 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -56,6 +56,7 @@
import android.window.TransitionInfo;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
@@ -72,6 +73,7 @@
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
+import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
@@ -149,10 +151,12 @@
return taskView;
}
- public static void createRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
- RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets, DepthController depthController,
+ public static void createRecentsWindowAnimator(
+ @NonNull TaskView v, boolean skipViewChanges,
+ @NonNull RemoteAnimationTargetCompat[] appTargets,
+ @NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
+ @NonNull RemoteAnimationTargetCompat[] nonAppTargets,
+ @Nullable DepthController depthController,
PendingAnimation out) {
RecentsView recentsView = v.getRecentsView();
boolean isQuickSwitch = v.isEndQuickswitchCuj();
@@ -192,7 +196,8 @@
boolean showAsGrid = dp.overviewShowAsGrid;
boolean parallaxCenterAndAdjacentTask =
taskIndex != recentsView.getCurrentPage() && !showAsGrid;
- int startScroll = recentsView.getScrollOffset(taskIndex);
+ int taskRectTranslationPrimary = recentsView.getScrollOffset(taskIndex);
+ int taskRectTranslationSecondary = showAsGrid ? (int) v.getGridTranslationY() : 0;
RemoteTargetHandle[] topMostSimulators = null;
@@ -209,9 +214,10 @@
tvsLocal.fullScreenProgress.value = 0;
tvsLocal.recentsViewScale.value = 1;
- tvsLocal.setScroll(startScroll);
tvsLocal.setIsGridTask(v.isGridTask());
- tvsLocal.setGridTranslationY(v.getGridTranslationY());
+ tvsLocal.getOrientationState().getOrientationHandler().set(tvsLocal,
+ TaskViewSimulator::setTaskRectTranslation, taskRectTranslationPrimary,
+ taskRectTranslationSecondary);
// Fade in the task during the initial 20% of the animation
out.addFloat(targetHandle.getTransformParams(), TransformParams.TARGET_ALPHA, 0, 1,
@@ -418,15 +424,46 @@
finishCallback.run();
}
- /** Legacy version (until shell transitions are enabled) */
- public static void composeRecentsSplitLaunchAnimatorLegacy(@NonNull Task initialTask,
+ /**
+ * Legacy version (until shell transitions are enabled)
+ *
+ * If {@param launchingTaskView} is not null, then this will play the tasks launch animation
+ * from the position of the GroupedTaskView (when user taps on the TaskView to start it).
+ * Technically this case should be taken care of by
+ * {@link #composeRecentsSplitLaunchAnimatorLegacy()} below, but the way we launch tasks whether
+ * it's a single task or multiple tasks results in different entry-points.
+ *
+ * If it is null, then it will simply fade in the starting apps and fade out launcher (for the
+ * case where launcher handles animating starting split tasks from app icon) */
+ public static void composeRecentsSplitLaunchAnimatorLegacy(
+ @Nullable GroupedTaskView launchingTaskView,
+ @NonNull Task initialTask,
@NonNull Task secondTask, @NonNull RemoteAnimationTargetCompat[] appTargets,
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
@NonNull RemoteAnimationTargetCompat[] nonAppTargets,
+ @NonNull StateManager stateManager,
+ @Nullable DepthController depthController,
@NonNull Runnable finishCallback) {
+ if (launchingTaskView != null) {
+ AnimatorSet animatorSet = new AnimatorSet();
+ RecentsView recentsView = launchingTaskView.getRecentsView();
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ finishCallback.run();
+ }
+ });
+ composeRecentsLaunchAnimator(animatorSet, launchingTaskView,
+ appTargets, wallpaperTargets, nonAppTargets,
+ true, stateManager,
+ recentsView, depthController);
+ animatorSet.start();
+ return;
+ }
+
final ArrayList<SurfaceControl> openingTargets = new ArrayList<>();
final ArrayList<SurfaceControl> closingTargets = new ArrayList<>();
-
for (RemoteAnimationTargetCompat appTarget : appTargets) {
final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
final int mode = appTarget.mode;
@@ -490,7 +527,7 @@
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
@NonNull RemoteAnimationTargetCompat[] nonAppTargets, boolean launcherClosing,
@NonNull StateManager stateManager, @NonNull RecentsView recentsView,
- @NonNull DepthController depthController) {
+ @Nullable DepthController depthController) {
boolean skipLauncherChanges = !launcherClosing;
TaskView taskView = findTaskViewToLaunch(recentsView, v, appTargets);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 377edbe..30dce61 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -289,6 +289,12 @@
.onSystemBarAttributesChanged(displayId, behavior));
}
+ @Override
+ public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
+ executeForTaskbarManager(() -> mTaskbarManager
+ .onNavButtonsDarkIntensityChanged(darkIntensity));
+ }
+
private void executeForTaskbarManager(final Runnable r) {
MAIN_EXECUTOR.execute(() -> {
if (mTaskbarManager == null) {
@@ -970,6 +976,7 @@
pw.println(" resumed=" + resumed);
pw.println(" mConsumer=" + mConsumer.getName());
ActiveGestureLog.INSTANCE.dump("", pw);
+ RecentsModel.INSTANCE.get(this).dump("", pw);
pw.println("ProtoTrace:");
pw.println(" file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
}
diff --git a/quickstep/src/com/android/quickstep/ViewUtils.java b/quickstep/src/com/android/quickstep/ViewUtils.java
index 184ab17..e290be8 100644
--- a/quickstep/src/com/android/quickstep/ViewUtils.java
+++ b/quickstep/src/com/android/quickstep/ViewUtils.java
@@ -15,8 +15,10 @@
*/
package com.android.quickstep;
+import android.graphics.HardwareRenderer;
import android.os.Handler;
import android.view.View;
+import android.view.ViewRootImpl;
import com.android.launcher3.Utilities;
import com.android.systemui.shared.system.ViewRootImplCompat;
@@ -45,9 +47,9 @@
return new FrameHandler(view, onFinishRunnable, canceled).schedule();
}
- private static class FrameHandler implements LongConsumer {
+ private static class FrameHandler implements HardwareRenderer.FrameDrawingCallback {
- final ViewRootImplCompat mViewRoot;
+ final ViewRootImpl mViewRoot;
final Runnable mFinishCallback;
final BooleanSupplier mCancelled;
final Handler mHandler;
@@ -55,14 +57,14 @@
int mDeferFrameCount = 1;
FrameHandler(View view, Runnable finishCallback, BooleanSupplier cancelled) {
- mViewRoot = new ViewRootImplCompat(view);
+ mViewRoot = view.getViewRootImpl();
mFinishCallback = finishCallback;
mCancelled = cancelled;
mHandler = new Handler();
}
@Override
- public void accept(long l) {
+ public void onFrameDraw(long frame) {
Utilities.postAsyncCallback(mHandler, this::onFrame);
}
@@ -83,7 +85,7 @@
}
private boolean schedule() {
- if (mViewRoot.isValid()) {
+ if (mViewRoot.getView() != null) {
mViewRoot.registerRtFrameCallback(this);
mViewRoot.getView().invalidate();
return true;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
index 510820a..162ace4 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
@@ -24,6 +24,8 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
+import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_GESTURE;
+import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_KEY;
import static com.android.launcher3.Utilities.squaredHypot;
import android.animation.Animator;
@@ -64,8 +66,6 @@
private static final String OPA_BUNDLE_TRIGGER = "triggered_by";
// From //java/com/google/android/apps/gsa/assistant/shared/proto/opa_trigger.proto.
private static final int OPA_BUNDLE_TRIGGER_DIAG_SWIPE_GESTURE = 83;
- private static final String INVOCATION_TYPE_KEY = "invocation_type";
- private static final int INVOCATION_TYPE_GESTURE = 1;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index b0c68c5..de7dbd6 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -49,7 +49,6 @@
import com.android.internal.app.ChooserActivity;
import com.android.launcher3.BuildConfig;
-import com.android.launcher3.testing.TestProtocol;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.utilities.BitmapUtil;
@@ -78,9 +77,6 @@
public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
Rect screenshotBounds,
Insets visibleInsets, Task.TaskKey task) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_SCREENSHOT, "image action utils calling into sysuiproxy");
- }
systemUiProxy.handleImageBundleAsScreenshot(BitmapUtil.hardwareBitmapToBundle(screenshot),
screenshotBounds, visibleInsets, task);
}
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 9c6fd3d..8ccab71 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -162,7 +162,7 @@
*/
public void setDeviceProfile(DeviceProfile deviceProfile) {
boolean oldMultipleOrientationsSupported = isMultipleOrientationSupportedByDevice();
- setFlag(FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY, !deviceProfile.allowRotation);
+ setFlag(FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY, !deviceProfile.isTablet);
if (mListenersInitialized) {
boolean newMultipleOrientationsSupported = isMultipleOrientationSupportedByDevice();
// If isMultipleOrientationSupportedByDevice is changed, init or destroy listeners
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 41aaa1a..c784d82 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -30,11 +30,18 @@
import android.view.SurfaceControl;
import android.window.TransitionInfo;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.statehandlers.DepthController;
+import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskViewUtils;
+import com.android.quickstep.views.GroupedTaskView;
+import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
@@ -52,23 +59,32 @@
private final Handler mHandler;
private final SystemUiProxy mSystemUiProxy;
+ private final StateManager mStateManager;
+ private final DepthController mDepthController;
private @StagePosition int mStagePosition;
private Task mInitialTask;
private Task mSecondTask;
private Rect mInitialBounds;
private boolean mRecentsAnimationRunning;
+ /** If not null, this is the TaskView we want to launch from */
+ @Nullable
+ private GroupedTaskView mLaunchingTaskView;
- public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
+ public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy,
+ StateManager stateManager,
+ DepthController depthController) {
mHandler = handler;
mSystemUiProxy = systemUiProxy;
+ mStateManager = stateManager;
+ mDepthController = depthController;
}
/**
* To be called after first task selected
*/
- public void setInitialTaskSelect(Task taskView, @StagePosition int stagePosition,
+ public void setInitialTaskSelect(Task task, @StagePosition int stagePosition,
Rect initialBounds) {
- mInitialTask = taskView;
+ mInitialTask = task;
mStagePosition = stagePosition;
mInitialBounds = initialBounds;
}
@@ -76,13 +92,25 @@
/**
* To be called after second task selected
*/
- public void setSecondTaskId(Task taskView, Consumer<Boolean> callback) {
- mSecondTask = taskView;
+ public void setSecondTaskId(Task task, Consumer<Boolean> callback) {
+ mSecondTask = task;
launchTasks(mInitialTask, mSecondTask, mStagePosition, callback,
false /* freezeTaskList */);
}
/**
+ * To be called when we want to launch split pairs from an existing GroupedTaskView.
+ */
+ public void launchTasks(GroupedTaskView groupedTaskView,
+ Consumer<Boolean> callback, boolean freezeTaskList) {
+ mLaunchingTaskView = groupedTaskView;
+ TaskView.TaskIdAttributeContainer[] taskIdAttributeContainers =
+ groupedTaskView.getTaskIdAttributeContainers();
+ launchTasks(taskIdAttributeContainers[0].getTask(), taskIdAttributeContainers[1].getTask(),
+ taskIdAttributeContainers[0].getStagePosition(), callback, freezeTaskList);
+ }
+
+ /**
* @param stagePosition representing location of task1
*/
public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition,
@@ -169,8 +197,9 @@
RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
Runnable finishedCallback) {
postAsyncCallback(mHandler,
- () -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask,
- mSecondTask, apps, wallpapers, nonApps, () -> {
+ () -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(
+ mLaunchingTaskView, mInitialTask, mSecondTask, apps, wallpapers,
+ nonApps, mStateManager, mDepthController, () -> {
finishedCallback.run();
if (mSuccessCallback != null) {
mSuccessCallback.accept(true);
@@ -201,6 +230,7 @@
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mInitialBounds = null;
mRecentsAnimationRunning = false;
+ mLaunchingTaskView = null;
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
index 3b4fd31..3b1c150 100644
--- a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
+++ b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
@@ -22,10 +22,10 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.View;
+import android.view.ViewRootImpl;
import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
-import com.android.systemui.shared.system.ViewRootImplCompat;
import java.util.function.Consumer;
@@ -41,7 +41,7 @@
private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
private final SurfaceControl mBarrierSurfaceControl;
- private final ViewRootImplCompat mTargetViewRootImpl;
+ private final ViewRootImpl mTargetViewRootImpl;
private final Handler mApplyHandler;
private int mLastSequenceNumber = 0;
@@ -50,8 +50,8 @@
* @param targetView The view in the surface that acts as synchronization anchor.
*/
public SurfaceTransactionApplier(View targetView) {
- mTargetViewRootImpl = new ViewRootImplCompat(targetView);
- mBarrierSurfaceControl = mTargetViewRootImpl.getRenderSurfaceControl();
+ mTargetViewRootImpl = targetView.getViewRootImpl();
+ mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
mApplyHandler = new Handler(this::onApplyMessage);
}
@@ -109,7 +109,7 @@
if (targetView == null) {
// No target view, no applier
callback.accept(null);
- } else if (new ViewRootImplCompat(targetView).isValid()) {
+ } else if (targetView.isAttachedToWindow()) {
// Already attached, we're good to go
callback.accept(new SurfaceTransactionApplier(targetView));
} else {
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 7d396ba..f676091 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -102,7 +102,8 @@
private StagedSplitBounds mStagedSplitBounds;
private boolean mDrawsBelowRecents;
private boolean mIsGridTask;
- private float mGridTranslationY;
+ private int mTaskRectTranslationX;
+ private int mTaskRectTranslationY;
public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
mContext = context;
@@ -157,15 +158,11 @@
fullTaskSize = new Rect(mTaskRect);
mOrientationState.getOrientationHandler()
.setSplitTaskSwipeRect(mDp, mTaskRect, mStagedSplitBounds, mStagePosition);
- if (mIsGridTask) {
- mTaskRect.offset(0, (int) mGridTranslationY);
- }
+ mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
} else {
fullTaskSize = mTaskRect;
}
- if (mIsGridTask) {
- fullTaskSize.offset(0, (int) mGridTranslationY);
- }
+ fullTaskSize.offset(mTaskRectTranslationX, mTaskRectTranslationY);
return mOrientationState.getFullScreenScaleAndPivot(fullTaskSize, mDp, mPivot);
}
@@ -225,10 +222,11 @@
}
/**
- * Sets the y-translation when overview is in grid.
+ * Apply translations on TaskRect's starting location.
*/
- public void setGridTranslationY(float gridTranslationY) {
- mGridTranslationY = gridTranslationY;
+ public void setTaskRectTranslation(int taskRectTranslationX, int taskRectTranslationY) {
+ mTaskRectTranslationX = taskRectTranslationX;
+ mTaskRectTranslationY = taskRectTranslationY;
}
/**
@@ -336,19 +334,19 @@
// Apply TaskView matrix: taskRect, translate
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
- mOrientationState.getOrientationHandler().set(mMatrix, MATRIX_POST_TRANSLATE,
+ mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
taskPrimaryTranslation.value);
mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
taskSecondaryTranslation.value);
+ mOrientationState.getOrientationHandler().setPrimary(
+ mMatrix, MATRIX_POST_TRANSLATE, recentsViewScroll.value);
// Apply RecentsView matrix
mMatrix.postScale(recentsViewScale.value, recentsViewScale.value, mPivot.x, mPivot.y);
mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
recentsViewSecondaryTranslation.value);
- mOrientationState.getOrientationHandler().set(mMatrix, MATRIX_POST_TRANSLATE,
+ mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
recentsViewPrimaryTranslation.value);
- mOrientationState.getOrientationHandler().set(
- mMatrix, MATRIX_POST_TRANSLATE, recentsViewScroll.value);
applyWindowToHomeRotation(mMatrix);
// Crop rect is the inverse of thumbnail matrix
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index c26837c..325ec04 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -73,6 +73,32 @@
mSplitPlaceholderView.setAlpha(0);
}
+ private void init(StatefulActivity launcher, TaskView originalView, RectF positionOut) {
+ mStartingPosition = positionOut;
+ updateInitialPositionForView(originalView);
+ final InsettableFrameLayout.LayoutParams lp =
+ (InsettableFrameLayout.LayoutParams) getLayoutParams();
+
+ mSplitPlaceholderView.setLayoutParams(new FrameLayout.LayoutParams(lp.width, lp.height));
+ positionOut.round(mOutline);
+ setPivotX(0);
+ setPivotY(0);
+
+ // Copy bounds of exiting thumbnail into ImageView
+ TaskThumbnailView thumbnail = originalView.getThumbnail();
+ mImageView.setImageBitmap(thumbnail.getThumbnail());
+ mImageView.setVisibility(VISIBLE);
+
+ mOrientationHandler = originalView.getRecentsView().getPagedOrientationHandler();
+ mSplitPlaceholderView.setIconView(originalView.getIconView(),
+ launcher.getDeviceProfile().overviewTaskIconDrawableSizePx);
+ mSplitPlaceholderView.getIconView().setRotation(mOrientationHandler.getDegreesRotated());
+ }
+
+ /**
+ * Configures and returns a an instance of {@link FloatingTaskView} initially matching the
+ * appearance of {@code originalView}.
+ */
public static FloatingTaskView getFloatingTaskView(StatefulActivity launcher,
TaskView originalView, RectF positionOut) {
final BaseDragLayer dragLayer = launcher.getDragLayer();
@@ -80,28 +106,7 @@
final FloatingTaskView floatingView = (FloatingTaskView) launcher.getLayoutInflater()
.inflate(R.layout.floating_split_select_view, parent, false);
- floatingView.mStartingPosition = positionOut;
- floatingView.updateInitialPositionForView(originalView);
- final InsettableFrameLayout.LayoutParams lp =
- (InsettableFrameLayout.LayoutParams) floatingView.getLayoutParams();
-
- floatingView.mSplitPlaceholderView.setLayoutParams(
- new FrameLayout.LayoutParams(lp.width, lp.height));
- positionOut.round(floatingView.mOutline);
- floatingView.setPivotX(0);
- floatingView.setPivotY(0);
-
- // Copy bounds of exiting thumbnail into ImageView
- TaskThumbnailView thumbnail = originalView.getThumbnail();
- floatingView.mImageView.setImageBitmap(thumbnail.getThumbnail());
- floatingView.mImageView.setVisibility(VISIBLE);
-
- floatingView.mOrientationHandler =
- originalView.getRecentsView().getPagedOrientationHandler();
- floatingView.mSplitPlaceholderView.setIconView(originalView.getIconView(),
- launcher.getDeviceProfile().overviewTaskIconDrawableSizePx);
- floatingView.mSplitPlaceholderView.getIconView()
- .setRotation(floatingView.mOrientationHandler.getDegreesRotated());
+ floatingView.init(launcher, originalView, positionOut);
parent.addView(floatingView);
return floatingView;
}
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index ea83b4d..4771d1e 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -76,7 +76,7 @@
mSecondaryTask = secondary;
mTaskIdContainer[1] = secondary.key.id;
mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2,
- STAGE_POSITION_BOTTOM_OR_RIGHT);
+ mIconView2, STAGE_POSITION_BOTTOM_OR_RIGHT);
mTaskIdAttributeContainer[0].setStagePosition(STAGE_POSITION_TOP_OR_LEFT);
mSnapshotView2.bind(secondary);
mSplitBoundsConfig = splitBoundsConfig;
@@ -117,14 +117,6 @@
}
}
- protected boolean showTaskMenuWithContainer(IconView iconView) {
- if (mActivity.getDeviceProfile().overviewShowAsGrid) {
- return TaskMenuViewWithArrow.Companion.showForTask(mTaskIdAttributeContainer[0]);
- } else {
- return TaskMenuView.showForTask(mTaskIdAttributeContainer[0]);
- }
- }
-
public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
mSplitBoundsConfig = stagedSplitBounds;
invalidate();
@@ -156,8 +148,8 @@
@Nullable
@Override
public RunnableList launchTaskAnimated() {
- getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- STAGE_POSITION_TOP_OR_LEFT, null /*callback*/,
+ getRecentsView().getSplitPlaceholder().launchTasks(this /*groupedTaskView*/,
+ null /*callback*/,
false /* freezeTaskList */);
return null;
}
diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java
index ccb1a99..5895c05 100644
--- a/quickstep/src/com/android/quickstep/views/IconView.java
+++ b/quickstep/src/com/android/quickstep/views/IconView.java
@@ -87,6 +87,14 @@
return mDrawable;
}
+ public int getDrawableWidth() {
+ return mDrawableWidth;
+ }
+
+ public int getDrawableHeight() {
+ return mDrawableHeight;
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index f3b6a63..b6bf59f 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -20,7 +20,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
@@ -31,7 +30,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.SysUINavigationMode;
@@ -114,10 +112,6 @@
protected void onFinishInflate() {
super.onFinishInflate();
findViewById(R.id.action_screenshot).setOnClickListener(this);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_SCREENSHOT, "Inflated OverviewActionsView and added screenshot"
- + " listener.");
- }
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
@@ -129,19 +123,11 @@
* @param callbacks for callbacks, or {@code null} to clear the listener.
*/
public void setCallbacks(T callbacks) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_SCREENSHOT, "OverviewActionsView setCallbacks: " + callbacks);
- }
mCallbacks = callbacks;
}
@Override
public void onClick(View view) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_SCREENSHOT, "OverviewActionsView - onClick"
- + " callbacks: " + mCallbacks + " view id: " + view.getId() + " "
- + " is screenshot? " + (view.getId() == R.id.action_screenshot));
- }
if (mCallbacks == null) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c065851..4b9b8a4 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -747,7 +747,7 @@
int primarySize = mOrientationHandler.getPrimaryValue(getWidth(), getHeight());
int scroll = OverScroll.dampedScroll(getUndampedOverScrollShift(), primarySize);
- mOrientationHandler.set(canvas, CANVAS_TRANSLATE, scroll);
+ mOrientationHandler.setPrimary(canvas, CANVAS_TRANSLATE, scroll);
if (mOverScrollShift != scroll) {
mOverScrollShift = scroll;
@@ -2612,10 +2612,8 @@
clampToProgress(FINAL_FRAME, 0, 0.5f));
});
}
- boolean isTaskInBottomGridRow = showAsGrid() && !mTopRowIdSet.contains(
- taskView.getTaskViewId()) && taskView.getTaskViewId() != mFocusedTaskViewId;
anim.setFloat(taskView, VIEW_ALPHA, 0,
- clampToProgress(isTaskInBottomGridRow ? ACCEL : FINAL_FRAME, 0, 0.5f));
+ clampToProgress(isOnGridBottomRow(taskView) ? ACCEL : FINAL_FRAME, 0, 0.5f));
FloatProperty<TaskView> secondaryViewTranslate =
taskView.getSecondaryDissmissTranslationProperty();
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
@@ -4357,15 +4355,22 @@
RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
mSplitBoundsConfig = gluer.getStagedSplitBounds();
- if (mSyncTransactionApplier != null) {
- // Add release check to the targets from the RemoteTargetGluer and not the targets
- // passed in because in the event we're in split screen, we use the passed in targets
- // to create new RemoteAnimationTargets in assignTargetsForSplitScreen(), and the
- // mSyncTransactionApplier doesn't get transferred over
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle
- .getTransformParams().getTargetSet()
- .addReleaseCheck(mSyncTransactionApplier));
- }
+ // Add release check to the targets from the RemoteTargetGluer and not the targets
+ // passed in because in the event we're in split screen, we use the passed in targets
+ // to create new RemoteAnimationTargets in assignTargetsForSplitScreen(), and the
+ // mSyncTransactionApplier doesn't get transferred over
+ runActionOnRemoteHandles(remoteTargetHandle -> {
+ final TransformParams params = remoteTargetHandle.getTransformParams();
+ if (mSyncTransactionApplier != null) {
+ params.setSyncTransactionApplier(mSyncTransactionApplier);
+ params.getTargetSet().addReleaseCheck(mSyncTransactionApplier);
+ }
+
+ TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
+ tvs.setOrientationState(mOrientationState);
+ tvs.setDp(mActivity.getDeviceProfile());
+ tvs.recentsViewScale.value = 1;
+ });
TaskView runningTaskView = getRunningTaskView();
if (runningTaskView instanceof GroupedTaskView) {
@@ -4375,12 +4380,6 @@
// notified.
((GroupedTaskView) runningTaskView).updateSplitBoundsConfig(mSplitBoundsConfig);
}
- for (RemoteTargetHandle remoteTargetHandle : mRemoteTargetHandles) {
- TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
- tvs.setOrientationState(mOrientationState);
- tvs.setDp(mActivity.getDeviceProfile());
- tvs.recentsViewScale.value = 1;
- }
}
/** Helper to avoid writing some for-loops to iterate over {@link #mRemoteTargetHandles} */
@@ -4680,6 +4679,15 @@
return position != -1 ? position : bottomRowIdArray.indexOf(taskView.getTaskViewId());
}
+ /**
+ * @return true if the task in on the top of the grid
+ */
+ public boolean isOnGridBottomRow(TaskView taskView) {
+ return showAsGrid()
+ && !mTopRowIdSet.contains(taskView.getTaskViewId())
+ && taskView.getTaskViewId() != mFocusedTaskViewId;
+ }
+
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
float degreesRotated;
if (navbarRotation == 0) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index 179fd68..06a5793 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -45,7 +45,10 @@
companion object {
const val TAG = "TaskMenuViewWithArrow"
- fun showForTask(taskContainer: TaskIdAttributeContainer): Boolean {
+ fun showForTask(
+ taskContainer: TaskIdAttributeContainer,
+ alignSecondRow: Boolean = false
+ ): Boolean {
val activity = BaseDraggingActivity
.fromContext<BaseDraggingActivity>(taskContainer.taskView.context)
val taskMenuViewWithArrow = activity.layoutInflater
@@ -55,7 +58,7 @@
false
) as TaskMenuViewWithArrow<*>
- return taskMenuViewWithArrow.populateAndShowForTask(taskContainer)
+ return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignSecondRow)
}
}
@@ -78,6 +81,9 @@
CLOSE_FADE_DURATION = CLOSE_CHILD_FADE_DURATION
}
+ private var alignSecondRow: Boolean = false
+ private val extraSpaceForSecondRowAlignment: Int
+ get() = if (alignSecondRow) optionMeasuredHeight else 0
private val menuWidth = context.resources.getDimensionPixelSize(R.dimen.task_menu_width_grid)
private lateinit var taskView: TaskView
@@ -91,10 +97,14 @@
else
0
+ private var iconView: IconView? = null
+ private var scrim: View? = null
+ private val scrimAlpha = 0.8f
+
override fun isOfType(type: Int): Boolean = type and TYPE_TASK_MENU != 0
override fun getTargetObjectLocation(outPos: Rect?) {
- popupContainer.getDescendantRectRelativeToSelf(taskView.iconView, outPos)
+ popupContainer.getDescendantRectRelativeToSelf(taskContainer.iconView, outPos)
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
@@ -112,18 +122,35 @@
optionLayout = findViewById(KtR.id.menu_option_layout)
}
- private fun populateAndShowForTask(taskContainer: TaskIdAttributeContainer): Boolean {
+ private fun populateAndShowForTask(
+ taskContainer: TaskIdAttributeContainer,
+ alignSecondRow: Boolean
+ ): Boolean {
if (isAttachedToWindow) {
return false
}
taskView = taskContainer.taskView
this.taskContainer = taskContainer
+ this.alignSecondRow = alignSecondRow
if (!populateMenu()) return false
+ addScrim()
show()
return true
}
+ private fun addScrim() {
+ scrim = View(context).apply {
+ layoutParams = FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.MATCH_PARENT
+ )
+ setBackgroundColor(Themes.getAttrColor(context, R.attr.overviewScrimColor))
+ alpha = 0f
+ }
+ popupContainer.addView(scrim)
+ }
+
/** @return true if successfully able to populate task view menu, false otherwise
*/
private fun populateMenu(): Boolean {
@@ -180,18 +207,50 @@
}
override fun onCreateOpenAnimation(anim: AnimatorSet) {
- anim.play(
- ObjectAnimator.ofFloat(
- taskContainer.thumbnailView, TaskThumbnailView.DIM_ALPHA,
- TaskView.MAX_PAGE_SCRIM_ALPHA
+ scrim?.let {
+ anim.play(
+ ObjectAnimator.ofFloat(it, View.ALPHA, 0f, scrimAlpha)
+ .setDuration(OPEN_DURATION.toLong())
)
- )
+ }
}
override fun onCreateCloseAnimation(anim: AnimatorSet) {
- anim.play(
- ObjectAnimator.ofFloat(taskContainer.thumbnailView, TaskThumbnailView.DIM_ALPHA, 0f)
- )
+ scrim?.let {
+ anim.play(
+ ObjectAnimator.ofFloat(it, View.ALPHA, scrimAlpha, 0f)
+ .setDuration(CLOSE_DURATION.toLong())
+ )
+ }
+ }
+
+ override fun closeComplete() {
+ super.closeComplete()
+ popupContainer.removeView(scrim)
+ popupContainer.removeView(iconView)
+ }
+
+ /**
+ * Copy the iconView from taskView to dragLayer so it can stay on top of the scrim.
+ * It needs to be called after [getTargetObjectLocation] because [mTempRect] needs to be
+ * populated.
+ */
+ private fun copyIconToDragLayer(insets: Rect) {
+ iconView = IconView(context).apply {
+ layoutParams = FrameLayout.LayoutParams(
+ taskContainer.iconView.width,
+ taskContainer.iconView.height
+ )
+ x = mTempRect.left.toFloat() - insets.left
+ y = mTempRect.top.toFloat() - insets.top
+ drawable = taskContainer.iconView.drawable
+ setDrawableSize(
+ taskContainer.iconView.drawableWidth,
+ taskContainer.iconView.drawableHeight
+ )
+ }
+
+ popupContainer.addView(iconView)
}
/**
@@ -217,7 +276,10 @@
val dragLayer: InsettableFrameLayout = popupContainer
val insets = dragLayer.insets
- // Put to the right of the icon if there is space, which means left aligned with the menu
+ copyIconToDragLayer(insets)
+
+ // Put this menu to the right of the icon if there is space,
+ // which means the arrow is left aligned with the menu
val rightAlignedMenuStartX = mTempRect.left - widthWithArrow
val leftAlignedMenuStartX = mTempRect.right + extraHorizontalSpace
mIsLeftAligned = if (mIsRtl) {
@@ -229,18 +291,17 @@
var menuStartX = if (mIsLeftAligned) leftAlignedMenuStartX else rightAlignedMenuStartX
- // Offset y so that the arrow and first row are center-aligned with the original icon.
+ // Offset y so that the arrow and row are center-aligned with the original icon.
val iconHeight = mTempRect.height()
- val optionHeight = optionMeasuredHeight
- val yOffset = (optionHeight - iconHeight) / 2
- var menuStartY = mTempRect.top - yOffset
+ val yOffset = (optionMeasuredHeight - iconHeight) / 2
+ var menuStartY = mTempRect.top - yOffset - extraSpaceForSecondRowAlignment
// Insets are added later, so subtract them now.
menuStartX -= insets.left
menuStartY -= insets.top
- setX(menuStartX.toFloat())
- setY(menuStartY.toFloat())
+ x = menuStartX.toFloat()
+ y = menuStartY.toFloat()
val lp = layoutParams as FrameLayout.LayoutParams
val arrowLp = mArrow.layoutParams as FrameLayout.LayoutParams
@@ -251,7 +312,8 @@
override fun addArrow() {
popupContainer.addView(mArrow)
mArrow.x = getArrowX()
- mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2)
+ mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2) +
+ extraSpaceForSecondRowAlignment
updateArrowColor()
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index f4944a6..e8077cf 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -541,7 +541,7 @@
mTask = task;
mTaskIdContainer[0] = mTask.key.id;
mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView,
- STAGE_POSITION_UNDEFINED);
+ mIconView, STAGE_POSITION_UNDEFINED);
mSnapshotView.bind(task);
setOrientationState(orientedState);
}
@@ -839,10 +839,14 @@
}
protected boolean showTaskMenuWithContainer(IconView iconView) {
+ TaskIdAttributeContainer menuContainer =
+ mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1];
if (mActivity.getDeviceProfile().overviewShowAsGrid) {
- return TaskMenuViewWithArrow.Companion.showForTask(mTaskIdAttributeContainer[0]);
+ boolean alignSecondRow = getRecentsView().isOnGridBottomRow(menuContainer.getTaskView())
+ && mActivity.getDeviceProfile().isLandscape;
+ return TaskMenuViewWithArrow.Companion.showForTask(menuContainer, alignSecondRow);
} else {
- return TaskMenuView.showForTask(mTaskIdAttributeContainer[0]);
+ return TaskMenuView.showForTask(menuContainer);
}
}
@@ -1571,15 +1575,17 @@
public class TaskIdAttributeContainer {
private final TaskThumbnailView mThumbnailView;
private final Task mTask;
+ private final IconView mIconView;
/** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
private @SplitConfigurationOptions.StagePosition int mStagePosition;
@IdRes
private final int mA11yNodeId;
public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView,
- int stagePosition) {
+ IconView iconView, int stagePosition) {
this.mTask = task;
this.mThumbnailView = thumbnailView;
+ this.mIconView = iconView;
this.mStagePosition = stagePosition;
this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ?
R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo;
@@ -1601,6 +1607,10 @@
return TaskView.this;
}
+ public IconView getIconView() {
+ return mIconView;
+ }
+
public int getStagePosition() {
return mStagePosition;
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index e64ea90..f2836ca 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -16,13 +16,10 @@
package com.android.launcher3;
-import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
-
import static com.android.launcher3.ResourceUtils.pxFromDp;
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
-import static com.android.launcher3.util.WindowManagerCompat.MIN_TABLET_WIDTH;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -64,7 +61,6 @@
public final boolean isPhone;
public final boolean transposeLayoutWithOrientation;
public final boolean isTwoPanels;
- public final boolean allowRotation;
// Device properties in current orientation
public final boolean isLandscape;
@@ -244,12 +240,7 @@
availableHeightPx = windowBounds.availableSize.y;
mInfo = info;
- // If the device's pixel density was scaled (usually via settings for A11y), use the
- // original dimensions to determine if rotation is allowed of not.
- float originalSmallestWidth = dpiFromPx(Math.min(widthPx, heightPx), DENSITY_DEVICE_STABLE);
- allowRotation = originalSmallestWidth >= MIN_TABLET_WIDTH;
- // Tablet UI does not support emulated landscape.
- isTablet = allowRotation && info.isTablet(windowBounds);
+ isTablet = info.isTablet(windowBounds);
isPhone = !isTablet;
isTwoPanels = isTablet && useTwoPanels;
@@ -1031,7 +1022,6 @@
writer.println(prefix + "DeviceProfile:");
writer.println(prefix + "\t1 dp = " + mMetrics.density + " px");
- writer.println(prefix + "\tallowRotation:" + allowRotation);
writer.println(prefix + "\tisTablet:" + isTablet);
writer.println(prefix + "\tisPhone:" + isPhone);
writer.println(prefix + "\ttransposeLayoutWithOrientation:"
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index cefadf7..1ce7ebe 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -252,7 +252,7 @@
if (0 <= mCurrentPage && mCurrentPage < getPageCount()) {
newPosition = getScrollForPage(mCurrentPage) + mCurrentPageScrollDiff;
}
- mOrientationHandler.set(this, VIEW_SCROLL_TO, newPosition);
+ mOrientationHandler.setPrimary(this, VIEW_SCROLL_TO, newPosition);
mScroller.startScroll(mScroller.getCurrX(), 0, newPosition - mScroller.getCurrX(), 0);
forceFinishScroller();
}
@@ -556,7 +556,7 @@
int oldPos = mOrientationHandler.getPrimaryScroll(this);
int newPos = mScroller.getCurrX();
if (oldPos != newPos) {
- mOrientationHandler.set(this, VIEW_SCROLL_TO, mScroller.getCurrX());
+ mOrientationHandler.setPrimary(this, VIEW_SCROLL_TO, mScroller.getCurrX());
}
if (mAllowOverScroll) {
@@ -1280,7 +1280,7 @@
mLastMotionRemainder = delta - movedDelta;
if (delta != 0) {
- mOrientationHandler.set(this, VIEW_SCROLL_BY, movedDelta);
+ mOrientationHandler.setPrimary(this, VIEW_SCROLL_BY, movedDelta);
if (mAllowOverScroll) {
final float pulledToX = oldScroll + delta;
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index f348a33..0c39632 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -49,6 +49,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import java.util.Collections;
@@ -253,12 +254,13 @@
case ALLOW_ROTATION_PREFERENCE_KEY:
DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.get(
getContext()).getDeviceProfile(getContext());
- if (deviceProfile.allowRotation) {
+ if (deviceProfile.isTablet) {
// Launcher supports rotation by default. No need to show this setting.
return false;
}
// Initialize the UI once
- preference.setDefaultValue(false);
+ preference.setDefaultValue(
+ RotationHelper.getAllowRotationDefaultValue(deviceProfile));
return true;
case FLAGS_PREFERENCE_KEY:
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 87871b1..867fd99 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -18,6 +18,10 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
+
+import static com.android.launcher3.Utilities.dpiFromPx;
+import static com.android.launcher3.util.WindowManagerCompat.MIN_TABLET_WIDTH;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@@ -25,7 +29,6 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
-import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.UiThreadHelper;
/**
@@ -38,6 +41,17 @@
public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
+ /**
+ * Returns the default value of {@link #ALLOW_ROTATION_PREFERENCE_KEY} preference.
+ */
+ public static boolean getAllowRotationDefaultValue(DeviceProfile deviceProfile) {
+ // If the device's pixel density was scaled (usually via settings for A11y), use the
+ // original dimensions to determine if rotation is allowed of not.
+ float originalSmallestWidth = dpiFromPx(
+ Math.min(deviceProfile.widthPx, deviceProfile.heightPx), DENSITY_DEVICE_STABLE);
+ return originalSmallestWidth >= MIN_TABLET_WIDTH;
+ }
+
public static final int REQUEST_NONE = 0;
public static final int REQUEST_ROTATE = 1;
public static final int REQUEST_LOCK = 2;
@@ -51,7 +65,7 @@
/**
* Rotation request made by
- * {@link ActivityTracker.SchedulerCallback}.
+ * {@link com.android.launcher3.util.ActivityTracker.SchedulerCallback}.
* This supersedes any other request.
*/
private int mStateHandlerRequest = REQUEST_NONE;
@@ -84,7 +98,7 @@
mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
}
mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
- mActivity.getDeviceProfile().allowRotation);
+ getAllowRotationDefaultValue(mActivity.getDeviceProfile()));
} else {
if (mSharedPrefs != null) {
mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
@@ -98,7 +112,7 @@
if (mDestroyed) return;
boolean wasRotationEnabled = mHomeRotationEnabled;
mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
- mActivity.getDeviceProfile().allowRotation);
+ getAllowRotationDefaultValue(mActivity.getDeviceProfile()));
if (mHomeRotationEnabled != wasRotationEnabled) {
notifyChange();
}
@@ -106,7 +120,7 @@
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
- boolean ignoreAutoRotateSettings = dp.allowRotation;
+ boolean ignoreAutoRotateSettings = dp.isTablet;
if (mIgnoreAutoRotateSettings != ignoreAutoRotateSettings) {
setIgnoreAutoRotateSettings(ignoreAutoRotateSettings);
notifyChange();
@@ -143,7 +157,7 @@
public void initialize() {
if (!mInitialized) {
mInitialized = true;
- setIgnoreAutoRotateSettings(mActivity.getDeviceProfile().allowRotation);
+ setIgnoreAutoRotateSettings(mActivity.getDeviceProfile().isTablet);
mActivity.addOnDeviceProfileChangeListener(this);
notifyChange();
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 9a74fb1..62b8a48 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -126,5 +126,4 @@
public static final String TASK_VIEW_ID_CRASH = "b/195430732";
public static final String NO_DROP_TARGET = "b/195031154";
public static final String NULL_INT_SET = "b/200572078";
- public static final String NO_SCREENSHOT = "b/202414125";
}
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 498f6db..e127074 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -101,12 +101,12 @@
}
@Override
- public <T> void set(T target, Int2DAction<T> action, int param) {
+ public <T> void setPrimary(T target, Int2DAction<T> action, int param) {
action.call(target, 0, param);
}
@Override
- public <T> void set(T target, Float2DAction<T> action, float param) {
+ public <T> void setPrimary(T target, Float2DAction<T> action, float param) {
action.call(target, 0, param);
}
@@ -116,6 +116,12 @@
}
@Override
+ public <T> void set(T target, Int2DAction<T> action, int primaryParam,
+ int secondaryParam) {
+ action.call(target, secondaryParam, primaryParam);
+ }
+
+ @Override
public float getPrimaryDirection(MotionEvent event, int pointerIndex) {
return event.getY(pointerIndex);
}
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 95336cd..d954552 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -65,9 +65,10 @@
Float2DAction<Canvas> CANVAS_TRANSLATE = Canvas::translate;
Float2DAction<Matrix> MATRIX_POST_TRANSLATE = Matrix::postTranslate;
- <T> void set(T target, Int2DAction<T> action, int param);
- <T> void set(T target, Float2DAction<T> action, float param);
+ <T> void setPrimary(T target, Int2DAction<T> action, int param);
+ <T> void setPrimary(T target, Float2DAction<T> action, float param);
<T> void setSecondary(T target, Float2DAction<T> action, float param);
+ <T> void set(T target, Int2DAction<T> action, int primaryParam, int secondaryParam);
float getPrimaryDirection(MotionEvent event, int pointerIndex);
float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId);
int getMeasuredSize(View view);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 835c240..fbc335c 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -101,12 +101,12 @@
}
@Override
- public <T> void set(T target, Int2DAction<T> action, int param) {
+ public <T> void setPrimary(T target, Int2DAction<T> action, int param) {
action.call(target, param, 0);
}
@Override
- public <T> void set(T target, Float2DAction<T> action, float param) {
+ public <T> void setPrimary(T target, Float2DAction<T> action, float param) {
action.call(target, param, 0);
}
@@ -116,6 +116,12 @@
}
@Override
+ public <T> void set(T target, Int2DAction<T> action, int primaryParam,
+ int secondaryParam) {
+ action.call(target, primaryParam, secondaryParam);
+ }
+
+ @Override
public float getPrimaryDirection(MotionEvent event, int pointerIndex) {
return event.getX(pointerIndex);
}
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 2068c29..c050c6c 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -261,6 +261,13 @@
PortraitSize realSize = new PortraitSize(newInfo.currentSize.x, newInfo.currentSize.y);
PortraitSize expectedSize = oldInfo.mInternalDisplays.get(
ApiWrapper.getUniqueId(display));
+ if (newInfo.supportedBounds.size() != oldInfo.supportedBounds.size()) {
+ Log.e("b/198965093",
+ "Inconsistent number of displays"
+ + "\ndisplay state: " + display.getState()
+ + "\noldInfo.supportedBounds: " + oldInfo.supportedBounds
+ + "\nnewInfo.supportedBounds: " + newInfo.supportedBounds);
+ }
if (!realSize.equals(expectedSize) && display.getState() == Display.STATE_OFF) {
Log.e("b/198965093", "Display size changed while display is off, ignoring change");
return;
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 44f2719..19dca45 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -38,6 +38,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.system.OsConstants;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -83,6 +84,7 @@
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -327,7 +329,12 @@
*/
protected <T> T getOnUiThread(final Callable<T> callback) {
try {
- return mMainThreadExecutor.submit(callback).get();
+ return mMainThreadExecutor.submit(callback).get(DEFAULT_UI_TIMEOUT,
+ TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ Log.e(TAG, "Timeout in getOnUiThread, sending SIGABRT", e);
+ Process.sendSignal(Process.myPid(), OsConstants.SIGABRT);
+ throw new RuntimeException(e);
} catch (Throwable e) {
throw new RuntimeException(e);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2fbe460..3485dd1 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -544,11 +544,11 @@
: TestHelpers.getSystemHealthMessage(getContext(), mTestStartTime);
if (systemHealth != null) {
- return message
- + ";\nPerhaps linked to system health problems:\n<<<<<<<<<<<<<<<<<<\n"
+ message += ";\nPerhaps linked to system health problems:\n<<<<<<<<<<<<<<<<<<\n"
+ systemHealth + "\n>>>>>>>>>>>>>>>>>>";
}
}
+ Log.d(TAG, "About to throw the error: " + message, new Exception());
return message;
}