Merge "Fix testQuickSwitchFromApp" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index 939656e..2755492 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -96,6 +96,7 @@
protected float mDragLengthFactor = 1;
protected final Context mContext;
+ protected final RecentsAnimationDeviceState mDeviceState;
protected final GestureState mGestureState;
protected final OverviewComponentObserver mOverviewComponentObserver;
protected final BaseActivityInterface<T> mActivityInterface;
@@ -106,7 +107,6 @@
protected final TransformParams mTransformParams = new TransformParams();
private final Vibrator mVibrator;
- protected final Mode mMode;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
@@ -135,10 +135,11 @@
protected boolean mCanceled;
protected int mFinishingRecentsAnimationForNewTaskId = -1;
- protected BaseSwipeUpHandler(Context context, GestureState gestureState,
- OverviewComponentObserver overviewComponentObserver,
+ protected BaseSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
+ GestureState gestureState, OverviewComponentObserver overviewComponentObserver,
RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
mContext = context;
+ mDeviceState = deviceState;
mGestureState = gestureState;
mOverviewComponentObserver = overviewComponentObserver;
mActivityInterface = gestureState.getActivityInterface();
@@ -147,7 +148,6 @@
mActivityInterface.createActivityInitListener(this::onActivityInit);
mRunningTaskId = runningTaskId;
mInputConsumer = inputConsumer;
- mMode = SysUINavigationMode.getMode(context);
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
@@ -348,7 +348,7 @@
mAppWindowAnimationHelper.updateHomeBounds(getStackBounds(dp));
}
mAppWindowAnimationHelper.updateTargetRect(TEMP_RECT);
- if (mMode == Mode.NO_BUTTON) {
+ if (mDeviceState.isFullyGesturalNavMode()) {
// We can drag all the way to the top of the screen.
mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index 17457aa..298b0ff 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -19,11 +19,11 @@
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import android.graphics.Matrix;
-import android.view.View;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.quickstep.views.TaskThumbnailView;
@@ -40,25 +40,24 @@
public class TaskOverlayFactory implements ResourceBasedOverride {
/** Note that these will be shown in order from top to bottom, if available for the task. */
- private static final TaskSystemShortcut[] MENU_OPTIONS = new TaskSystemShortcut[]{
- new TaskSystemShortcut.AppInfo(),
- new TaskSystemShortcut.SplitScreen(),
- new TaskSystemShortcut.Pin(),
- new TaskSystemShortcut.Install(),
- new TaskSystemShortcut.Freeform()
+ private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[]{
+ TaskShortcutFactory.APP_INFO,
+ TaskShortcutFactory.SPLIT_SCREEN,
+ TaskShortcutFactory.PIN,
+ TaskShortcutFactory.INSTALL,
+ TaskShortcutFactory.FREE_FORM
};
public static final MainThreadInitializedObject<TaskOverlayFactory> INSTANCE =
forOverride(TaskOverlayFactory.class, R.string.task_overlay_factory_class);
- public List<TaskSystemShortcut> getEnabledShortcuts(TaskView taskView) {
- final ArrayList<TaskSystemShortcut> shortcuts = new ArrayList<>();
+ public List<SystemShortcut> getEnabledShortcuts(TaskView taskView) {
+ final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
- for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
- View.OnClickListener onClickListener =
- menuOption.getOnClickListener(activity, taskView);
- if (onClickListener != null) {
- shortcuts.add(menuOption);
+ for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
+ SystemShortcut shortcut = menuOption.getShortcut(activity, taskView);
+ if (shortcut != null) {
+ shortcuts.add(shortcut);
}
}
return shortcuts;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
new file mode 100644
index 0000000..a3a1d6d
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2018 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.quickstep;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.view.View;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.WorkspaceItemInfo;
+import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.popup.SystemShortcut.AppInfo;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.InstantAppResolver;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
+import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
+import com.android.systemui.shared.recents.view.RecentsTransition;
+import com.android.systemui.shared.system.ActivityCompat;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.ActivityOptionsCompat;
+import com.android.systemui.shared.system.WindowManagerWrapper;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Represents a system shortcut that can be shown for a recent task.
+ */
+public interface TaskShortcutFactory {
+
+ SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view);
+
+ static WorkspaceItemInfo dummyInfo(TaskView view) {
+ Task task = view.getTask();
+
+ WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
+ dummyInfo.intent = new Intent();
+ ComponentName component = task.getTopComponent();
+ dummyInfo.intent.setComponent(component);
+ dummyInfo.user = UserHandle.of(task.key.userId);
+ dummyInfo.title = TaskUtils.getTitle(view.getContext(), task);
+ return dummyInfo;
+ }
+
+ TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, dummyInfo(view));
+
+ abstract class MultiWindowFactory implements TaskShortcutFactory {
+
+ private final int mIconRes;
+ private final int mTextRes;
+
+ MultiWindowFactory(int iconRes, int textRes) {
+ mIconRes = iconRes;
+ mTextRes = textRes;
+ }
+
+ protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId);
+ protected abstract ActivityOptions makeLaunchOptions(Activity activity);
+ protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
+
+ @Override
+ public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
+ final Task task = taskView.getTask();
+ if (!task.isDockable) {
+ return null;
+ }
+ if (!isAvailable(activity, task.key.displayId)) {
+ return null;
+ }
+ return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this);
+ }
+ }
+
+ class MultiWindowSystemShortcut extends SystemShortcut {
+
+ private Handler mHandler;
+
+ private final RecentsView mRecentsView;
+ private final TaskThumbnailView mThumbnailView;
+ private final TaskView mTaskView;
+ private final MultiWindowFactory mFactory;
+
+ public MultiWindowSystemShortcut(int iconRes, int textRes,
+ BaseDraggingActivity activity, TaskView taskView, MultiWindowFactory factory) {
+ super(iconRes, textRes, activity, dummyInfo(taskView));
+
+ mHandler = new Handler(Looper.getMainLooper());
+ mTaskView = taskView;
+ mRecentsView = activity.getOverviewPanel();
+ mThumbnailView = taskView.getThumbnail();
+ mFactory = factory;
+ }
+
+ @Override
+ public void onClick(View view) {
+ Task.TaskKey taskKey = mTaskView.getTask().key;
+ final int taskId = taskKey.id;
+
+ final View.OnLayoutChangeListener onLayoutChangeListener =
+ new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int l, int t, int r, int b,
+ int oldL, int oldT, int oldR, int oldB) {
+ mTaskView.getRootView().removeOnLayoutChangeListener(this);
+ mRecentsView.clearIgnoreResetTask(taskId);
+
+ // Start animating in the side pages once launcher has been resized
+ mRecentsView.dismissTask(mTaskView, false, false);
+ }
+ };
+
+ final DeviceProfile.OnDeviceProfileChangeListener onDeviceProfileChangeListener =
+ new DeviceProfile.OnDeviceProfileChangeListener() {
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ mTarget.removeOnDeviceProfileChangeListener(this);
+ if (dp.isMultiWindowMode) {
+ mTaskView.getRootView().addOnLayoutChangeListener(
+ onLayoutChangeListener);
+ }
+ }
+ };
+
+ dismissTaskMenuView(mTarget);
+
+ ActivityOptions options = mFactory.makeLaunchOptions(mTarget);
+ if (options != null
+ && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
+ options)) {
+ if (!mFactory.onActivityStarted(mTarget)) {
+ return;
+ }
+ // Add a device profile change listener to kick off animating the side tasks
+ // once we enter multiwindow mode and relayout
+ mTarget.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
+
+ final Runnable animStartedListener = () -> {
+ // Hide the task view and wait for the window to be resized
+ // TODO: Consider animating in launcher and do an in-place start activity
+ // afterwards
+ mRecentsView.setIgnoreResetTask(taskId);
+ mTaskView.setAlpha(0f);
+ };
+
+ final int[] position = new int[2];
+ mThumbnailView.getLocationOnScreen(position);
+ final int width = (int) (mThumbnailView.getWidth() * mTaskView.getScaleX());
+ final int height = (int) (mThumbnailView.getHeight() * mTaskView.getScaleY());
+ final Rect taskBounds = new Rect(position[0], position[1],
+ position[0] + width, position[1] + height);
+
+ // Take the thumbnail of the task without a scrim and apply it back after
+ float alpha = mThumbnailView.getDimAlpha();
+ mThumbnailView.setDimAlpha(0);
+ Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
+ taskBounds.width(), taskBounds.height(), mThumbnailView, 1f,
+ Color.BLACK);
+ mThumbnailView.setDimAlpha(alpha);
+
+ AppTransitionAnimationSpecsFuture future =
+ new AppTransitionAnimationSpecsFuture(mHandler) {
+ @Override
+ public List<AppTransitionAnimationSpecCompat> composeSpecs() {
+ return Collections.singletonList(new AppTransitionAnimationSpecCompat(
+ taskId, thumbnail, taskBounds));
+ }
+ };
+ WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
+ future, animStartedListener, mHandler, true /* scaleUp */,
+ taskKey.displayId);
+ }
+ }
+ }
+
+ TaskShortcutFactory SPLIT_SCREEN = new MultiWindowFactory(
+ R.drawable.ic_split_screen, R.string.recent_task_option_split_screen) {
+
+ @Override
+ protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
+ // Don't show menu-item if already in multi-window and the task is from
+ // the secondary display.
+ // TODO(b/118266305): Temporarily disable splitscreen for secondary display while new
+ // implementation is enabled
+ return !activity.getDeviceProfile().isMultiWindowMode
+ && (displayId == -1 || displayId == DEFAULT_DISPLAY);
+ }
+
+ @Override
+ protected ActivityOptions makeLaunchOptions(Activity activity) {
+ final ActivityCompat act = new ActivityCompat(activity);
+ final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(
+ act.getDisplayId());
+ if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
+ return null;
+ }
+ boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT;
+ return ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft);
+ }
+
+ @Override
+ protected boolean onActivityStarted(BaseDraggingActivity activity) {
+ SystemUiProxy.INSTANCE.get(activity).onSplitScreenInvoked();
+ activity.getUserEventDispatcher().logActionOnControl(TAP,
+ LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
+ return true;
+ }
+ };
+
+ TaskShortcutFactory FREE_FORM = new MultiWindowFactory(
+ R.drawable.ic_split_screen, R.string.recent_task_option_freeform) {
+
+ @Override
+ protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
+ return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity);
+ }
+
+ @Override
+ protected ActivityOptions makeLaunchOptions(Activity activity) {
+ ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
+ // Arbitrary bounds only because freeform is in dev mode right now
+ Rect r = new Rect(50, 50, 200, 200);
+ activityOptions.setLaunchBounds(r);
+ return activityOptions;
+ }
+
+ @Override
+ protected boolean onActivityStarted(BaseDraggingActivity activity) {
+ activity.returnToHomescreen();
+ return true;
+ }
+ };
+
+ TaskShortcutFactory PIN = (activity, tv) -> {
+ if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
+ return null;
+ }
+ if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
+ return null;
+ }
+ if (ActivityManagerWrapper.getInstance().isLockToAppActive()) {
+ // We shouldn't be able to pin while an app is locked.
+ return null;
+ }
+ return new PinSystemShortcut(activity, tv);
+ };
+
+ class PinSystemShortcut extends SystemShortcut {
+
+ private static final String TAG = "PinSystemShortcut";
+
+ private final TaskView mTaskView;
+
+ public PinSystemShortcut(BaseDraggingActivity target, TaskView tv) {
+ super(R.drawable.ic_pin, R.string.recent_task_option_pin, target, dummyInfo(tv));
+ mTaskView = tv;
+ }
+
+ @Override
+ public void onClick(View view) {
+ Consumer<Boolean> resultCallback = success -> {
+ if (success) {
+ SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning(
+ mTaskView.getTask().key.id);
+ } else {
+ mTaskView.notifyTaskLaunchFailed(TAG);
+ }
+ };
+ mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler());
+ dismissTaskMenuView(mTarget);
+ }
+ }
+
+ TaskShortcutFactory INSTALL = (activity, view) ->
+ InstantAppResolver.newInstance(activity).isInstantApp(activity,
+ view.getTask().getTopComponent().getPackageName())
+ ? new SystemShortcut.Install(activity, dummyInfo(view)) : null;
+
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
deleted file mode 100644
index 5a2e3ff..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2018 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.quickstep;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
-
-import android.app.Activity;
-import android.app.ActivityOptions;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.view.View;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.ItemInfo;
-import com.android.launcher3.R;
-import com.android.launcher3.WorkspaceItemInfo;
-import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.util.InstantAppResolver;
-import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskThumbnailView;
-import com.android.quickstep.views.TaskView;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
-import com.android.systemui.shared.recents.view.RecentsTransition;
-import com.android.systemui.shared.system.ActivityCompat;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.WindowManagerWrapper;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * Represents a system shortcut that can be shown for a recent task.
- */
-public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut {
-
- private static final String TAG = "TaskSystemShortcut";
-
- protected T mSystemShortcut;
-
- public TaskSystemShortcut(T systemShortcut) {
- super(systemShortcut);
- mSystemShortcut = systemShortcut;
- }
-
- protected TaskSystemShortcut(int iconResId, int labelResId) {
- super(iconResId, labelResId);
- }
-
- @Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- return null;
- }
-
- public View.OnClickListener getOnClickListener(BaseDraggingActivity activity, TaskView view) {
- Task task = view.getTask();
-
- WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
- dummyInfo.intent = new Intent();
- ComponentName component = task.getTopComponent();
- dummyInfo.intent.setComponent(component);
- dummyInfo.user = UserHandle.of(task.key.userId);
- dummyInfo.title = TaskUtils.getTitle(activity, task);
-
- return getOnClickListenerForTask(activity, task, dummyInfo);
- }
-
- protected View.OnClickListener getOnClickListenerForTask(
- BaseDraggingActivity activity, Task task, ItemInfo dummyInfo) {
- return mSystemShortcut.getOnClickListener(activity, dummyInfo);
- }
-
- public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> {
- public AppInfo() {
- super(new SystemShortcut.AppInfo());
- }
- }
-
- public static abstract class MultiWindow extends TaskSystemShortcut {
-
- private Handler mHandler;
-
- public MultiWindow(int iconRes, int textRes) {
- super(iconRes, textRes);
- mHandler = new Handler(Looper.getMainLooper());
- }
-
- protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId);
- protected abstract ActivityOptions makeLaunchOptions(Activity activity);
- protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
-
- @Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, TaskView taskView) {
- final Task task = taskView.getTask();
- final int taskId = task.key.id;
- final int displayId = task.key.displayId;
- if (!task.isDockable) {
- return null;
- }
- if (!isAvailable(activity, displayId)) {
- return null;
- }
- final RecentsView recentsView = activity.getOverviewPanel();
-
- final TaskThumbnailView thumbnailView = taskView.getThumbnail();
- return (v -> {
- final View.OnLayoutChangeListener onLayoutChangeListener =
- new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int l, int t, int r, int b,
- int oldL, int oldT, int oldR, int oldB) {
- taskView.getRootView().removeOnLayoutChangeListener(this);
- recentsView.clearIgnoreResetTask(taskId);
-
- // Start animating in the side pages once launcher has been resized
- recentsView.dismissTask(taskView, false, false);
- }
- };
-
- final DeviceProfile.OnDeviceProfileChangeListener onDeviceProfileChangeListener =
- new DeviceProfile.OnDeviceProfileChangeListener() {
- @Override
- public void onDeviceProfileChanged(DeviceProfile dp) {
- activity.removeOnDeviceProfileChangeListener(this);
- if (dp.isMultiWindowMode) {
- taskView.getRootView().addOnLayoutChangeListener(
- onLayoutChangeListener);
- }
- }
- };
-
- dismissTaskMenuView(activity);
-
- ActivityOptions options = makeLaunchOptions(activity);
- if (options != null
- && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
- options)) {
- if (!onActivityStarted(activity)) {
- return;
- }
- // Add a device profile change listener to kick off animating the side tasks
- // once we enter multiwindow mode and relayout
- activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
-
- final Runnable animStartedListener = () -> {
- // Hide the task view and wait for the window to be resized
- // TODO: Consider animating in launcher and do an in-place start activity
- // afterwards
- recentsView.setIgnoreResetTask(taskId);
- taskView.setAlpha(0f);
- };
-
- final int[] position = new int[2];
- thumbnailView.getLocationOnScreen(position);
- final int width = (int) (thumbnailView.getWidth() * taskView.getScaleX());
- final int height = (int) (thumbnailView.getHeight() * taskView.getScaleY());
- final Rect taskBounds = new Rect(position[0], position[1],
- position[0] + width, position[1] + height);
-
- // Take the thumbnail of the task without a scrim and apply it back after
- float alpha = thumbnailView.getDimAlpha();
- thumbnailView.setDimAlpha(0);
- Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
- taskBounds.width(), taskBounds.height(), thumbnailView, 1f,
- Color.BLACK);
- thumbnailView.setDimAlpha(alpha);
-
- AppTransitionAnimationSpecsFuture future =
- new AppTransitionAnimationSpecsFuture(mHandler) {
- @Override
- public List<AppTransitionAnimationSpecCompat> composeSpecs() {
- return Collections.singletonList(new AppTransitionAnimationSpecCompat(
- taskId, thumbnail, taskBounds));
- }
- };
- WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
- future, animStartedListener, mHandler, true /* scaleUp */, displayId);
- }
- });
- }
- }
-
- public static class SplitScreen extends MultiWindow {
- public SplitScreen() {
- super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
- }
-
- @Override
- protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
- // Don't show menu-item if already in multi-window and the task is from
- // the secondary display.
- // TODO(b/118266305): Temporarily disable splitscreen for secondary display while new
- // implementation is enabled
- return !activity.getDeviceProfile().isMultiWindowMode
- && (displayId == -1 || displayId == DEFAULT_DISPLAY);
- }
-
- @Override
- protected ActivityOptions makeLaunchOptions(Activity activity) {
- final ActivityCompat act = new ActivityCompat(activity);
- final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(
- act.getDisplayId());
- if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
- return null;
- }
- boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT;
- return ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft);
- }
-
- @Override
- protected boolean onActivityStarted(BaseDraggingActivity activity) {
- SystemUiProxy.INSTANCE.get(activity).onSplitScreenInvoked();
- activity.getUserEventDispatcher().logActionOnControl(TAP,
- LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
- return true;
- }
- }
-
- public static class Freeform extends MultiWindow {
- public Freeform() {
- super(R.drawable.ic_split_screen, R.string.recent_task_option_freeform);
- }
-
- @Override
- protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
- return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity);
- }
-
- @Override
- protected ActivityOptions makeLaunchOptions(Activity activity) {
- ActivityOptions activityOptions = ActivityOptionsCompat.makeFreeformOptions();
- // Arbitrary bounds only because freeform is in dev mode right now
- Rect r = new Rect(50, 50, 200, 200);
- activityOptions.setLaunchBounds(r);
- return activityOptions;
- }
-
- @Override
- protected boolean onActivityStarted(BaseDraggingActivity activity) {
- activity.returnToHomescreen();
- return true;
- }
- }
-
- public static class Pin extends TaskSystemShortcut {
-
- private static final String TAG = Pin.class.getSimpleName();
-
- private Handler mHandler;
-
- public Pin() {
- super(R.drawable.ic_pin, R.string.recent_task_option_pin);
- mHandler = new Handler(Looper.getMainLooper());
- }
-
- @Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, TaskView taskView) {
- if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
- return null;
- }
- if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
- return null;
- }
- if (ActivityManagerWrapper.getInstance().isLockToAppActive()) {
- // We shouldn't be able to pin while an app is locked.
- return null;
- }
- return view -> {
- Consumer<Boolean> resultCallback = success -> {
- if (success) {
- SystemUiProxy.INSTANCE.get(activity).startScreenPinning(
- taskView.getTask().key.id);
- } else {
- taskView.notifyTaskLaunchFailed(TAG);
- }
- };
- taskView.launchTask(true, resultCallback, mHandler);
- dismissTaskMenuView(activity);
- };
- }
- }
-
- public static class Install extends TaskSystemShortcut<SystemShortcut.Install> {
- public Install() {
- super(new SystemShortcut.Install());
- }
-
- @Override
- protected View.OnClickListener getOnClickListenerForTask(
- BaseDraggingActivity activity, Task task, ItemInfo itemInfo) {
- if (InstantAppResolver.newInstance(activity).isInstantApp(activity,
- task.getTopComponent().getPackageName())) {
- return mSystemShortcut.createOnClickListener(activity, itemInfo);
- }
- return null;
- }
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 8d7a534..b4df81a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -63,8 +63,6 @@
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.TraceHelper;
-import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
import com.android.quickstep.inputconsumers.AssistantInputConsumer;
import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
@@ -114,8 +112,7 @@
* Service connected by system-UI for handling touch interaction.
*/
@TargetApi(Build.VERSION_CODES.Q)
-public class TouchInteractionService extends Service implements
- NavigationModeChangeListener, PluginListener<OverscrollPlugin> {
+public class TouchInteractionService extends Service implements PluginListener<OverscrollPlugin> {
private static final String TAG = "TouchInteractionService";
@@ -269,20 +266,18 @@
private InputMonitorCompat mInputMonitorCompat;
private InputEventReceiver mInputEventReceiver;
- private Mode mMode = Mode.THREE_BUTTONS;
@Override
public void onCreate() {
super.onCreate();
- mDeviceState = new RecentsAnimationDeviceState(this);
- mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
-
// Initialize anything here that is needed in direct boot mode.
// Everything else should be initialized in onUserUnlocked() below.
mMainChoreographer = Choreographer.getInstance();
mAM = ActivityManagerWrapper.getInstance();
+ mDeviceState = new RecentsAnimationDeviceState(this);
+ mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
+ mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
- onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this));
sConnected = true;
PluginManagerWrapper.INSTANCE.get(getBaseContext()).addPluginListener(this,
@@ -308,7 +303,7 @@
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "initInputMonitor 1");
}
disposeEventHandlers();
- if (!mMode.hasGestures || !SystemUiProxy.INSTANCE.get(this).isActive()) {
+ if (mDeviceState.isButtonNavMode() || !SystemUiProxy.INSTANCE.get(this).isActive()) {
return;
}
if (TestProtocol.sDebugTracing) {
@@ -327,12 +322,10 @@
mDeviceState.updateGestureTouchRegions();
}
- @Override
- public void onNavigationModeChanged(Mode newMode) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onNavigationModeChanged " + newMode);
- }
- mMode = newMode;
+ /**
+ * Called when the navigation mode changes, guaranteed to be after the device state has updated.
+ */
+ private void onNavigationModeChanged(SysUINavigationMode.Mode mode) {
initInputMonitor();
resetHomeBounceSeenOnQuickstepEnabledFirstTime();
}
@@ -369,7 +362,7 @@
}
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
- if (!mDeviceState.isUserUnlocked() || !mMode.hasGestures) {
+ if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
// Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
// mode doesn't have gestures
return;
@@ -417,7 +410,6 @@
}
disposeEventHandlers();
mDeviceState.destroy();
- SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
SystemUiProxy.INSTANCE.get(this).setProxy(null);
sConnected = false;
@@ -453,7 +445,8 @@
ActiveGestureLog.INSTANCE.addLog("setInputConsumer", mConsumer.getType());
mUncheckedConsumer = mConsumer;
- } else if (mDeviceState.isUserUnlocked() && mMode == Mode.NO_BUTTON
+ } else if (mDeviceState.isUserUnlocked()
+ && mDeviceState.isFullyGesturalNavMode()
&& mDeviceState.canTriggerAssistantAction(event)) {
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we should
// not interrupt it. QuickSwitch assumes that interruption can only happen if the
@@ -494,7 +487,7 @@
|| previousGestureState.isRecentsAnimationRunning()
? newBaseConsumer(previousGestureState, newGestureState, event)
: mResetGestureInputConsumer;
- if (mMode == Mode.NO_BUTTON) {
+ if (mDeviceState.isFullyGesturalNavMode()) {
if (mDeviceState.canTriggerAssistantAction(event)) {
base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat);
}
@@ -584,7 +577,8 @@
final boolean shouldDefer;
final BaseSwipeUpHandler.Factory factory;
- if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
+ if (mDeviceState.isFullyGesturalNavMode()
+ && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
shouldDefer = previousGestureState.getFinishingRecentsAnimationTaskId() < 0;
factory = mFallbackNoButtonFactory;
} else {
@@ -601,7 +595,7 @@
private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState,
RunningTaskInfo taskInfo) {
- if (mMode == Mode.NO_BUTTON && taskInfo != null) {
+ if (mDeviceState.isFullyGesturalNavMode() && taskInfo != null) {
return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
gestureState, mInputMonitorCompat, taskInfo.taskId);
} else {
@@ -641,7 +635,7 @@
if (!mDeviceState.isUserUnlocked()) {
return;
}
- if (!mMode.hasGestures && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
+ if (mDeviceState.isButtonNavMode() && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
// Prevent the overview from being started before the real home on first boot.
return;
}
@@ -708,7 +702,6 @@
// Dump everything
mDeviceState.dump(pw);
pw.println("TouchState:");
- pw.println(" navMode=" + mMode);
boolean resumed = mOverviewComponentObserver != null
&& mOverviewComponentObserver.getActivityInterface().isResumed();
pw.println(" resumed=" + resumed);
@@ -748,9 +741,9 @@
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(GestureState gestureState,
RunningTaskInfo runningTask, long touchTimeMs, boolean continuingLastGesture,
boolean isLikelyToStartNewTask) {
- return new FallbackNoButtonInputConsumer(this, gestureState, mOverviewComponentObserver,
- runningTask, mRecentsModel, mInputConsumer, isLikelyToStartNewTask,
- continuingLastGesture);
+ return new FallbackNoButtonInputConsumer(this, mDeviceState, gestureState,
+ mOverviewComponentObserver, runningTask, mRecentsModel, mInputConsumer,
+ isLikelyToStartNewTask, continuingLastGesture);
}
protected boolean shouldNotifyBackGesture() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index f1b3598..8e9c898 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -157,9 +157,7 @@
*/
private static final int LOG_NO_OP_PAGE_INDEX = -1;
- private final RecentsAnimationDeviceState mDeviceState;
private final TaskAnimationManager mTaskAnimationManager;
- private final GestureState mGestureState;
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
@@ -198,11 +196,9 @@
RunningTaskInfo runningTaskInfo, long touchTimeMs,
OverviewComponentObserver overviewComponentObserver, boolean continuingLastGesture,
InputConsumerController inputConsumer, RecentsModel recentsModel) {
- super(context, gestureState, overviewComponentObserver, recentsModel, inputConsumer,
- runningTaskInfo.id);
- mDeviceState = deviceState;
+ super(context, deviceState, gestureState, overviewComponentObserver, recentsModel,
+ inputConsumer, runningTaskInfo.id);
mTaskAnimationManager = taskAnimationManager;
- mGestureState = gestureState;
mTouchTimeMs = touchTimeMs;
mContinuingLastGesture = continuingLastGesture;
initStateCallbacks();
@@ -444,7 +440,7 @@
* Note this method has no effect unless the navigation mode is NO_BUTTON.
*/
private void maybeUpdateRecentsAttachedState(boolean animate) {
- if (mMode != Mode.NO_BUTTON || mRecentsView == null) {
+ if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
return;
}
RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets == null
@@ -546,7 +542,7 @@
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (passed != mPassedOverviewThreshold) {
mPassedOverviewThreshold = passed;
- if (mMode != Mode.NO_BUTTON) {
+ if (!mDeviceState.isFullyGesturalNavMode()) {
performHapticFeedback();
}
}
@@ -730,7 +726,7 @@
if (!isFling) {
if (isCancel) {
endTarget = LAST_TASK;
- } else if (mMode == Mode.NO_BUTTON) {
+ } else if (mDeviceState.isFullyGesturalNavMode()) {
if (mIsShelfPeeking) {
endTarget = RECENTS;
} else if (goingToNewTask) {
@@ -751,9 +747,9 @@
boolean willGoToNewTaskOnSwipeUp =
goingToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity);
- if (mMode == Mode.NO_BUTTON && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
+ if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
endTarget = HOME;
- } else if (mMode == Mode.NO_BUTTON && isSwipeUp && !mIsShelfPeeking) {
+ } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsShelfPeeking) {
// If swiping at a diagonal, base end target on the faster velocity.
endTarget = NEW_TASK;
} else if (isSwipeUp) {
@@ -793,7 +789,7 @@
float minFlingVelocity = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
- if (endTarget == RECENTS && mMode != Mode.NO_BUTTON) {
+ if (endTarget == RECENTS && !mDeviceState.isFullyGesturalNavMode()) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
startShift, endShift, endShift, endVelocity / 1000,
mTransitionDragLength, mContext);
@@ -839,7 +835,7 @@
}
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
- if (mMode == Mode.NO_BUTTON) {
+ if (mDeviceState.isFullyGesturalNavMode()) {
setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
}
} else if (endTarget == NEW_TASK || endTarget == LAST_TASK) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index 152b9c9..7b24bd9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -50,6 +50,7 @@
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.RecentsAnimationController;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RectFSpringAnim;
@@ -112,13 +113,13 @@
private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
private RunningWindowAnim mFinishAnimation;
- public FallbackNoButtonInputConsumer(Context context, GestureState gestureState,
- OverviewComponentObserver overviewComponentObserver,
+ public FallbackNoButtonInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
+ GestureState gestureState, OverviewComponentObserver overviewComponentObserver,
RunningTaskInfo runningTaskInfo, RecentsModel recentsModel,
InputConsumerController inputConsumer,
boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
- super(context, gestureState, overviewComponentObserver, recentsModel, inputConsumer,
- runningTaskInfo.id);
+ super(context, deviceState, gestureState, overviewComponentObserver, recentsModel,
+ inputConsumer, runningTaskInfo.id);
mLauncherAlpha.value = 1;
mRunningTaskInfo = runningTaskInfo;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index c479250..aeab4b5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -54,8 +54,6 @@
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationDeviceState;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.CachedEventDispatcher;
@@ -85,7 +83,6 @@
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
private final InputMonitorCompat mInputMonitorCompat;
- private final SysUINavigationMode.Mode mMode;
private final BaseActivityInterface mActivityInterface;
private final BaseSwipeUpHandler.Factory mHandlerFactory;
@@ -137,7 +134,6 @@
mGestureState = gestureState;
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
- mMode = SysUINavigationMode.getMode(base);
mHandlerFactory = handlerFactory;
mActivityInterface = mGestureState.getActivityInterface();
@@ -293,7 +289,7 @@
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
}
- if (mMode == Mode.NO_BUTTON) {
+ if (mDeviceState.isFullyGesturalNavMode()) {
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|| isLikelyToStartNewTask);
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
index 07d0796..b810c4a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,7 +16,6 @@
package com.android.quickstep.views;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
import android.animation.Animator;
@@ -26,7 +25,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@@ -41,16 +39,13 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
-import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.TaskOverlayFactory;
-import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.IconView.OnScaleUpdateListener;
-import java.util.List;
-
/**
* Contains options for a recent task when long-pressing its icon.
*/
@@ -197,22 +192,16 @@
params.topMargin = (int) -mThumbnailTopMargin;
mTaskIcon.setLayoutParams(params);
- final BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext());
- final List<TaskSystemShortcut> shortcuts =
- TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(taskView);
- final int count = shortcuts.size();
- for (int i = 0; i < count; ++i) {
- final TaskSystemShortcut menuOption = shortcuts.get(i);
- addMenuOption(menuOption, menuOption.getOnClickListener(activity, taskView));
- }
+ TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(taskView)
+ .forEach(this::addMenuOption);
}
- private void addMenuOption(TaskSystemShortcut menuOption, OnClickListener onClickListener) {
+ private void addMenuOption(SystemShortcut menuOption) {
ViewGroup menuOptionView = (ViewGroup) mActivity.getLayoutInflater().inflate(
R.layout.task_view_menu_option, this, false);
menuOption.setIconAndLabelFor(
menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
- menuOptionView.setOnClickListener(onClickListener);
+ menuOptionView.setOnClickListener(menuOption);
mOptionLayout.addView(menuOptionView);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index bfb9613..3af0f70 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -53,6 +53,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -61,7 +62,6 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
-import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.TaskCornerRadius;
@@ -713,15 +713,9 @@
getContext().getText(R.string.accessibility_close_task)));
final Context context = getContext();
- final List<TaskSystemShortcut> shortcuts =
- TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this);
- final int count = shortcuts.size();
- for (int i = 0; i < count; ++i) {
- final TaskSystemShortcut menuOption = shortcuts.get(i);
- OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, this);
- if (onClickListener != null) {
- info.addAction(menuOption.createAccessibilityAction(context));
- }
+ for (SystemShortcut s : TaskOverlayFactory.INSTANCE.get(getContext())
+ .getEnabledShortcuts(this)) {
+ info.addAction(s.createAccessibilityAction(context));
}
if (mDigitalWellBeingToast.hasLimit()) {
@@ -752,16 +746,10 @@
return true;
}
- final List<TaskSystemShortcut> shortcuts =
- TaskOverlayFactory.INSTANCE.get(getContext()).getEnabledShortcuts(this);
- final int count = shortcuts.size();
- for (int i = 0; i < count; ++i) {
- final TaskSystemShortcut menuOption = shortcuts.get(i);
- if (menuOption.hasHandlerForAction(action)) {
- OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, this);
- if (onClickListener != null) {
- onClickListener.onClick(this);
- }
+ for (SystemShortcut s : TaskOverlayFactory.INSTANCE.get(getContext())
+ .getEnabledShortcuts(this)) {
+ if (s.hasHandlerForAction(action)) {
+ s.onClick(this);
return true;
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index e6e3297..1855e64 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
+import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
@@ -43,6 +44,7 @@
import android.graphics.Region;
import android.os.Process;
import android.text.TextUtils;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
@@ -52,7 +54,9 @@
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
+import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -65,7 +69,7 @@
* Manages the state of the system during a swipe up gesture.
*/
public class RecentsAnimationDeviceState implements
- SysUINavigationMode.NavigationModeChangeListener,
+ NavigationModeChangeListener,
DefaultDisplay.DisplayInfoChangeListener {
private Context mContext;
@@ -74,6 +78,8 @@
private DefaultDisplay mDefaultDisplay;
private int mDisplayId;
+ private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
+
private @SystemUiStateFlags int mSystemUiStateFlags;
private SysUINavigationMode.Mode mMode = THREE_BUTTONS;
@@ -114,6 +120,7 @@
mContext.registerReceiver(mUserUnlockedReceiver,
new IntentFilter(ACTION_USER_UNLOCKED));
}
+ runOnDestroy(() -> Utilities.unregisterReceiverSafely(mContext, mUserUnlockedReceiver));
// Register for exclusion updates
mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
@@ -124,7 +131,11 @@
mExclusionRegion = region;
}
};
+ runOnDestroy(mExclusionListener::unregister);
+
+ // Register for navigation mode changes
onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(this));
+ runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
// Add any blocked activities
String blockingActivity = context.getString(R.string.gesture_blocking_activity);
@@ -133,18 +144,34 @@
}
}
+ private void runOnDestroy(Runnable action) {
+ mOnDestroyActions.add(action);
+ }
+
/**
* Cleans up all the registered listeners and receivers.
*/
public void destroy() {
- Utilities.unregisterReceiverSafely(mContext, mUserUnlockedReceiver);
- mSysUiNavMode.removeModeChangeListener(this);
+ for (Runnable r : mOnDestroyActions) {
+ r.run();
+ }
mDefaultDisplay.removeChangeListener(this);
- mExclusionListener.unregister();
+ }
+
+ /**
+ * Adds a listener for the nav mode change, guaranteed to be called after the device state's
+ * mode has changed.
+ */
+ public void addNavigationModeChangedCallback(NavigationModeChangeListener listener) {
+ listener.onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(listener));
+ runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(listener));
}
@Override
public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onNavigationModeChanged " + newMode);
+ }
mDefaultDisplay.removeChangeListener(this);
if (newMode.hasGestures) {
mDefaultDisplay.addChangeListener(this);
@@ -168,6 +195,34 @@
}
/**
+ * @return the current navigation mode for the device.
+ */
+ public SysUINavigationMode.Mode getNavMode() {
+ return mMode;
+ }
+
+ /**
+ * @return whether the current nav mode is fully gestural.
+ */
+ public boolean isFullyGesturalNavMode() {
+ return mMode == NO_BUTTON;
+ }
+
+ /**
+ * @return whether the current nav mode has some gestures (either 2 or 0 button mode).
+ */
+ public boolean isGesturalNavMode() {
+ return mMode == TWO_BUTTONS || mMode == NO_BUTTON;
+ }
+
+ /**
+ * @return whether the current nav mode is button-based.
+ */
+ public boolean isButtonNavMode() {
+ return mMode == THREE_BUTTONS;
+ }
+
+ /**
* @return the display id for the display that Launcher is running on.
*/
public int getDisplayId() {
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 4833c26..8e5d852 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -382,8 +382,7 @@
@Override
public void onWidgetsBound() {
ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
- SystemShortcut widgetInfo = new SystemShortcut.Widgets();
- View.OnClickListener onClickListener = widgetInfo.getOnClickListener(mLauncher, itemInfo);
+ SystemShortcut widgetInfo = SystemShortcut.WIDGETS.getShortcut(mLauncher, itemInfo);
View widgetsView = null;
int count = mSystemShortcutContainer.getChildCount();
for (int i = 0; i < count; i++) {
@@ -394,7 +393,7 @@
}
}
- if (onClickListener != null && widgetsView == null) {
+ if (widgetInfo != null && widgetsView == null) {
// We didn't have any widgets cached but now there are some, so enable the shortcut.
if (mSystemShortcutContainer != this) {
initializeSystemShortcut(
@@ -407,7 +406,7 @@
close(false);
PopupContainerWithArrow.showForIcon(mOriginalIcon);
}
- } else if (onClickListener == null && widgetsView != null) {
+ } else if (widgetInfo == null && widgetsView != null) {
// No widgets exist, but we previously added the shortcut so remove it.
if (mSystemShortcutContainer != this) {
mSystemShortcutContainer.removeView(widgetsView);
@@ -430,8 +429,7 @@
info.setIconAndContentDescriptionFor((ImageView) view);
}
view.setTag(info);
- view.setOnClickListener(info.getOnClickListener(mLauncher,
- (ItemInfo) mOriginalIcon.getTag()));
+ view.setOnClickListener(info);
}
/**
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 5a5fbab..8751202 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -16,13 +16,19 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.app.RemoteAction;
+import android.content.Context;
import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
+import android.os.Build;
import android.util.Log;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.ImageView;
+import android.widget.TextView;
import android.widget.Toast;
import com.android.launcher3.AbstractFloatingView;
@@ -32,55 +38,75 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
+@TargetApi(Build.VERSION_CODES.Q)
public class RemoteActionShortcut extends SystemShortcut<BaseDraggingActivity> {
private static final String TAG = "RemoteActionShortcut";
private static final boolean DEBUG = Utilities.IS_DEBUG_DEVICE;
private final RemoteAction mAction;
- public RemoteActionShortcut(RemoteAction action) {
- super(action.getIcon(), action.getTitle(), action.getContentDescription(),
- R.id.action_remote_action_shortcut);
+ public RemoteActionShortcut(RemoteAction action,
+ BaseDraggingActivity activity, ItemInfo itemInfo) {
+ super(0, R.id.action_remote_action_shortcut, activity, itemInfo);
mAction = action;
}
@Override
- public View.OnClickListener getOnClickListener(
- final BaseDraggingActivity activity, final ItemInfo itemInfo) {
- return view -> {
- AbstractFloatingView.closeAllOpenViews(activity);
+ public void setIconAndLabelFor(View iconView, TextView labelView) {
+ mAction.getIcon().loadDrawableAsync(iconView.getContext(),
+ iconView::setBackground,
+ MAIN_EXECUTOR.getHandler());
+ labelView.setText(mAction.getTitle());
+ }
- final String actionIdentity = mAction.getTitle() + ", " +
- itemInfo.getTargetComponent().getPackageName();
- try {
- if (DEBUG) Log.d(TAG, "Sending action: " + actionIdentity);
- mAction.getActionIntent().send(
- activity,
- 0,
- new Intent().putExtra(
- Intent.EXTRA_PACKAGE_NAME,
- itemInfo.getTargetComponent().getPackageName()),
- (pendingIntent, intent, resultCode, resultData, resultExtras) -> {
- if (DEBUG) Log.d(TAG, "Action is complete: " + actionIdentity);
- if (resultData != null && !resultData.isEmpty()) {
- Log.e(TAG, "Remote action returned result: " + actionIdentity
- + " : " + resultData);
- Toast.makeText(activity, resultData, Toast.LENGTH_SHORT).show();
- }
- },
- new Handler(Looper.getMainLooper()));
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Remote action canceled: " + actionIdentity, e);
- Toast.makeText(activity, activity.getString(
- R.string.remote_action_failed,
- mAction.getTitle()),
- Toast.LENGTH_SHORT)
- .show();
- }
+ @Override
+ public void setIconAndContentDescriptionFor(ImageView view) {
+ mAction.getIcon().loadDrawableAsync(view.getContext(),
+ view::setImageDrawable,
+ MAIN_EXECUTOR.getHandler());
+ view.setContentDescription(mAction.getContentDescription());
+ }
- activity.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
- LauncherLogProto.ControlType.REMOTE_ACTION_SHORTCUT, view);
- };
+ @Override
+ public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(Context context) {
+ return new AccessibilityNodeInfo.AccessibilityAction(
+ R.id.action_remote_action_shortcut, mAction.getContentDescription());
+ }
+
+ @Override
+ public void onClick(View view) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+
+ final String actionIdentity = mAction.getTitle() + ", "
+ + mItemInfo.getTargetComponent().getPackageName();
+ try {
+ if (DEBUG) Log.d(TAG, "Sending action: " + actionIdentity);
+ mAction.getActionIntent().send(
+ mTarget,
+ 0,
+ new Intent().putExtra(
+ Intent.EXTRA_PACKAGE_NAME,
+ mItemInfo.getTargetComponent().getPackageName()),
+ (pendingIntent, intent, resultCode, resultData, resultExtras) -> {
+ if (DEBUG) Log.d(TAG, "Action is complete: " + actionIdentity);
+ if (resultData != null && !resultData.isEmpty()) {
+ Log.e(TAG, "Remote action returned result: " + actionIdentity
+ + " : " + resultData);
+ Toast.makeText(mTarget, resultData, Toast.LENGTH_SHORT).show();
+ }
+ },
+ MAIN_EXECUTOR.getHandler());
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Remote action canceled: " + actionIdentity, e);
+ Toast.makeText(mTarget, mTarget.getString(
+ R.string.remote_action_failed,
+ mAction.getTitle()),
+ Toast.LENGTH_SHORT)
+ .show();
+ }
+
+ mTarget.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
+ LauncherLogProto.ControlType.REMOTE_ACTION_SHORTCUT, view);
}
@Override
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index a87b7b8..222c6c9 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -5,14 +5,13 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
-import android.graphics.drawable.Icon;
-import android.os.Handler;
-import android.os.Looper;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ItemInfo;
@@ -39,41 +38,30 @@
* Example system shortcuts, defined as inner classes, include Widgets and AppInfo.
* @param <T>
*/
-public abstract class SystemShortcut<T extends BaseDraggingActivity>
- extends ItemInfo {
+public abstract class SystemShortcut<T extends BaseDraggingActivity> extends ItemInfo
+ implements View.OnClickListener {
+
private final int mIconResId;
private final int mLabelResId;
- private final Icon mIcon;
- private final CharSequence mLabel;
- private final CharSequence mContentDescription;
private final int mAccessibilityActionId;
- public SystemShortcut(int iconResId, int labelResId) {
+ protected final T mTarget;
+ protected final ItemInfo mItemInfo;
+
+ public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo) {
mIconResId = iconResId;
mLabelResId = labelResId;
mAccessibilityActionId = labelResId;
- mIcon = null;
- mLabel = null;
- mContentDescription = null;
+ mTarget = target;
+ mItemInfo = itemInfo;
}
- public SystemShortcut(Icon icon, CharSequence label, CharSequence contentDescription,
- int accessibilityActionId) {
- mIcon = icon;
- mLabel = label;
- mContentDescription = contentDescription;
- mAccessibilityActionId = accessibilityActionId;
- mIconResId = 0;
- mLabelResId = 0;
- }
-
- public SystemShortcut(SystemShortcut other) {
+ public SystemShortcut(SystemShortcut<T> other) {
mIconResId = other.mIconResId;
mLabelResId = other.mLabelResId;
- mIcon = other.mIcon;
- mLabel = other.mLabel;
- mContentDescription = other.mContentDescription;
mAccessibilityActionId = other.mAccessibilityActionId;
+ mTarget = other.mTarget;
+ mItemInfo = other.mItemInfo;
}
/**
@@ -84,150 +72,135 @@
}
public void setIconAndLabelFor(View iconView, TextView labelView) {
- if (mIcon != null) {
- mIcon.loadDrawableAsync(iconView.getContext(),
- iconView::setBackground,
- new Handler(Looper.getMainLooper()));
- } else {
- iconView.setBackgroundResource(mIconResId);
- }
-
- if (mLabel != null) {
- labelView.setText(mLabel);
- } else {
- labelView.setText(mLabelResId);
- }
+ iconView.setBackgroundResource(mIconResId);
+ labelView.setText(mLabelResId);
}
public void setIconAndContentDescriptionFor(ImageView view) {
- if (mIcon != null) {
- mIcon.loadDrawableAsync(view.getContext(),
- view::setImageDrawable,
- new Handler(Looper.getMainLooper()));
- } else {
- view.setImageResource(mIconResId);
- }
-
- view.setContentDescription(getContentDescription(view.getContext()));
- }
-
- private CharSequence getContentDescription(Context context) {
- return mContentDescription != null ? mContentDescription : context.getText(mLabelResId);
+ view.setImageResource(mIconResId);
+ view.setContentDescription(view.getContext().getText(mLabelResId));
}
public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(Context context) {
- return new AccessibilityNodeInfo.AccessibilityAction(mAccessibilityActionId,
- getContentDescription(context));
+ return new AccessibilityNodeInfo.AccessibilityAction(
+ mAccessibilityActionId, context.getText(mLabelResId));
}
public boolean hasHandlerForAction(int action) {
return mAccessibilityActionId == action;
}
- public abstract View.OnClickListener getOnClickListener(T activity, ItemInfo itemInfo);
+ public interface Factory<T extends BaseDraggingActivity> {
+
+ @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo);
+ }
+
+ public static final Factory<Launcher> WIDGETS = (launcher, itemInfo) -> {
+ if (itemInfo.getTargetComponent() == null) return null;
+ final List<WidgetItem> widgets =
+ launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
+ itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
+ if (widgets == null) {
+ return null;
+ }
+ return new Widgets(launcher, itemInfo);
+ };
public static class Widgets extends SystemShortcut<Launcher> {
- public Widgets() {
- super(R.drawable.ic_widget, R.string.widget_button_text);
+ public Widgets(Launcher target, ItemInfo itemInfo) {
+ super(R.drawable.ic_widget, R.string.widget_button_text, target, itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(final Launcher launcher,
- final ItemInfo itemInfo) {
- if (itemInfo.getTargetComponent() == null) return null;
- final List<WidgetItem> widgets =
- launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
- itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
- if (widgets == null) {
- return null;
- }
- return (view) -> {
- AbstractFloatingView.closeAllOpenViews(launcher);
- WidgetsBottomSheet widgetsBottomSheet =
- (WidgetsBottomSheet) launcher.getLayoutInflater().inflate(
- R.layout.widgets_bottom_sheet, launcher.getDragLayer(), false);
- widgetsBottomSheet.populateAndShow(itemInfo);
- launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.WIDGETS_BUTTON, view);
- };
+ public void onClick(View view) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+ WidgetsBottomSheet widgetsBottomSheet =
+ (WidgetsBottomSheet) mTarget.getLayoutInflater().inflate(
+ R.layout.widgets_bottom_sheet, mTarget.getDragLayer(), false);
+ widgetsBottomSheet.populateAndShow(mItemInfo);
+ mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+ ControlType.WIDGETS_BUTTON, view);
}
}
+ public static final Factory<BaseDraggingActivity> APP_INFO = AppInfo::new;
+
public static class AppInfo extends SystemShortcut {
- public AppInfo() {
- super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label);
+
+ public AppInfo(BaseDraggingActivity target, ItemInfo itemInfo) {
+ super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,
+ itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- return (view) -> {
- dismissTaskMenuView(activity);
- Rect sourceBounds = activity.getViewBounds(view);
- new PackageManagerHelper(activity).startDetailsActivityForInfo(
- itemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
- activity.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.APPINFO_TARGET, view);
- };
+ public void onClick(View view) {
+ dismissTaskMenuView(mTarget);
+ Rect sourceBounds = mTarget.getViewBounds(view);
+ new PackageManagerHelper(mTarget).startDetailsActivityForInfo(
+ mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
+ mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+ ControlType.APPINFO_TARGET, view);
}
}
+ public static Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> {
+ boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo)
+ && ((WorkspaceItemInfo) itemInfo).hasStatusFlag(
+ WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
+ boolean isInstantApp = false;
+ if (itemInfo instanceof com.android.launcher3.AppInfo) {
+ com.android.launcher3.AppInfo appInfo = (com.android.launcher3.AppInfo) itemInfo;
+ isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
+ }
+ boolean enabled = supportsWebUI || isInstantApp;
+ if (!enabled) {
+ return null;
+ }
+ return new Install(activity, itemInfo);
+ };
+
public static class Install extends SystemShortcut {
- public Install() {
- super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label);
+
+ public Install(BaseDraggingActivity target, ItemInfo itemInfo) {
+ super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label,
+ target, itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo) &&
- ((WorkspaceItemInfo) itemInfo).hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
- boolean isInstantApp = false;
- if (itemInfo instanceof com.android.launcher3.AppInfo) {
- com.android.launcher3.AppInfo appInfo = (com.android.launcher3.AppInfo) itemInfo;
- isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
- }
- boolean enabled = supportsWebUI || isInstantApp;
- if (!enabled) {
- return null;
- }
- return createOnClickListener(activity, itemInfo);
- }
-
- public View.OnClickListener createOnClickListener(
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- return view -> {
- Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
- itemInfo.getTargetComponent().getPackageName());
- activity.startActivitySafely(view, intent, itemInfo, null);
- AbstractFloatingView.closeAllOpenViews(activity);
- };
+ public void onClick(View view) {
+ Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
+ mItemInfo.getTargetComponent().getPackageName());
+ mTarget.startActivitySafely(view, intent, mItemInfo, null);
+ AbstractFloatingView.closeAllOpenViews(mTarget);
}
}
+ public static Factory<Launcher> DISMISS_PREDICTION = (launcher, itemInfo) -> {
+ if (!FeatureFlags.ENABLE_PREDICTION_DISMISS.get()) return null;
+ if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_PREDICTION) return null;
+ return new DismissPrediction(launcher, itemInfo);
+ };
+
public static class DismissPrediction extends SystemShortcut<Launcher> {
- public DismissPrediction() {
- super(R.drawable.ic_remove_no_shadow, R.string.dismiss_prediction_label);
+ public DismissPrediction(Launcher launcher, ItemInfo itemInfo) {
+ super(R.drawable.ic_remove_no_shadow, R.string.dismiss_prediction_label, launcher,
+ itemInfo);
}
@Override
- public View.OnClickListener getOnClickListener(Launcher activity, ItemInfo itemInfo) {
- if (!FeatureFlags.ENABLE_PREDICTION_DISMISS.get()) return null;
- if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_PREDICTION) return null;
- return (view) -> {
- PopupContainerWithArrow.closeAllOpenViews(activity);
- activity.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
- ControlType.DISMISS_PREDICTION, ContainerType.DEEPSHORTCUTS);
- AppLaunchTracker.INSTANCE.get(view.getContext())
- .onDismissApp(itemInfo.getTargetComponent(),
- itemInfo.user,
- AppLaunchTracker.CONTAINER_PREDICTIONS);
- };
+ public void onClick(View view) {
+ PopupContainerWithArrow.closeAllOpenViews(mTarget);
+ mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+ ControlType.DISMISS_PREDICTION, ContainerType.DEEPSHORTCUTS);
+ AppLaunchTracker.INSTANCE.get(view.getContext()).onDismissApp(
+ mItemInfo.getTargetComponent(),
+ mItemInfo.user,
+ AppLaunchTracker.CONTAINER_PREDICTIONS);
}
}
- protected static void dismissTaskMenuView(BaseDraggingActivity activity) {
+ public static void dismissTaskMenuView(BaseDraggingActivity activity) {
AbstractFloatingView.closeOpenViews(activity, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
}
diff --git a/src/com/android/launcher3/popup/SystemShortcutFactory.java b/src/com/android/launcher3/popup/SystemShortcutFactory.java
index dfcc2f8..8b8a4d0 100644
--- a/src/com/android/launcher3/popup/SystemShortcutFactory.java
+++ b/src/com/android/launcher3/popup/SystemShortcutFactory.java
@@ -34,25 +34,24 @@
forOverride(SystemShortcutFactory.class, R.string.system_shortcut_factory_class);
/** Note that these are in order of priority. */
- private final SystemShortcut[] mAllShortcuts;
+ private final SystemShortcut.Factory[] mAllFactories;
@SuppressWarnings("unused")
public SystemShortcutFactory() {
- this(new SystemShortcut.AppInfo(),
- new SystemShortcut.Widgets(),
- new SystemShortcut.Install(),
- new SystemShortcut.DismissPrediction());
+ this(SystemShortcut.APP_INFO, SystemShortcut.WIDGETS, SystemShortcut.INSTALL,
+ SystemShortcut.DISMISS_PREDICTION);
}
- protected SystemShortcutFactory(SystemShortcut... shortcuts) {
- mAllShortcuts = shortcuts;
+ protected SystemShortcutFactory(SystemShortcut.Factory... factories) {
+ mAllFactories = factories;
}
public @NonNull List<SystemShortcut> getEnabledShortcuts(Launcher launcher, ItemInfo info) {
List<SystemShortcut> systemShortcuts = new ArrayList<>();
- for (SystemShortcut systemShortcut : mAllShortcuts) {
- if (systemShortcut.getOnClickListener(launcher, info) != null) {
- systemShortcuts.add(systemShortcut);
+ for (SystemShortcut.Factory factory : mAllFactories) {
+ SystemShortcut shortcut = factory.getShortcut(launcher, info);
+ if (shortcut != null) {
+ systemShortcuts.add(shortcut);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index e1e9b8d..cc92327 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -163,7 +163,7 @@
"Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS,
++attempts <= MAX_SCROLL_ATTEMPTS);
- mLauncher.scroll(allAppsContainer, Direction.UP, margins, 50);
+ mLauncher.scroll(allAppsContainer, Direction.UP, margins, 12);
}
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 484cbb6..c90c8f6 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -424,11 +424,7 @@
// b/136278866
for (int i = 0; i != 100; ++i) {
if (getNavigationModeMismatchError() == null) break;
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ sleep(100);
}
final String error = getNavigationModeMismatchError();
@@ -803,7 +799,7 @@
0,
0,
Math.max(bottomMargin, getBottomGestureMargin(container))),
- 150);
+ 70);
}
void scroll(UiObject2 container, Direction direction, Rect margins, int steps) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 4f8aeb1..16a64a7 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -58,7 +58,7 @@
getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD),
mLauncher.getDevice().getDisplayWidth() / 2,
0,
- 50,
+ 12,
ALL_APPS_STATE_ORDINAL);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index d1261e0..db3314e 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -38,7 +38,7 @@
* Operations on the workspace screen.
*/
public final class Workspace extends Home {
- private static final int DRAG_DURACTION = 2000;
+ private static final int DRAG_DURATION = 500;
private static final int FLING_STEPS = 10;
private final UiObject2 mHotseat;
@@ -72,7 +72,7 @@
start.y,
start.x,
start.y - swipeHeight - mLauncher.getTouchSlop(),
- 60,
+ 12,
ALL_APPS_STATE_ORDINAL);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
@@ -166,7 +166,7 @@
launcher.waitForLauncherObject(longPressIndicator);
LauncherInstrumentation.log("dragIconToWorkspace: indicator");
launcher.movePointer(
- downTime, SystemClock.uptimeMillis(), DRAG_DURACTION, launchableCenter, dest);
+ downTime, SystemClock.uptimeMillis(), DRAG_DURATION, launchableCenter, dest);
LauncherInstrumentation.log("dragIconToWorkspace: moved pointer");
launcher.sendPointer(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest);