Merge "Reduce animation time for some common TAPL actions (affects jank/perf tests)" into ub-launcher3-master
diff --git a/Android.mk b/Android.mk
index 3d1d996..5def65f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -200,7 +200,7 @@
$(LOCAL_PATH)/quickstep/recents_ui_overrides/res
LOCAL_FULL_LIBS_MANIFEST_FILES := \
- $(LOCAL_PATH)/AndroidManifest.xml \
+ $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
$(LOCAL_PATH)/AndroidManifest-common.xml
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
@@ -247,7 +247,7 @@
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/go/AndroidManifest.xml \
- $(LOCAL_PATH)/AndroidManifest.xml \
+ $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
$(LOCAL_PATH)/AndroidManifest-common.xml
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
@@ -293,7 +293,7 @@
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/go/AndroidManifest.xml \
- $(LOCAL_PATH)/AndroidManifest.xml \
+ $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
$(LOCAL_PATH)/AndroidManifest-common.xml
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/go/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
new file mode 100644
index 0000000..0c60468
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
+import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController;
+import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
+import com.android.launcher3.util.TouchController;
+import com.android.quickstep.SysUINavigationMode;
+
+import java.util.ArrayList;
+
+public class QuickstepLauncher extends BaseQuickstepLauncher {
+
+ public static final boolean GO_LOW_RAM_RECENTS_ENABLED = true;
+
+ @Override
+ public TouchController[] createTouchControllers() {
+ ArrayList<TouchController> list = new ArrayList<>();
+ list.add(getDragController());
+
+ if (getDeviceProfile().isVerticalBarLayout()) {
+ list.add(new LandscapeStatesTouchController(this));
+ list.add(new LandscapeEdgeSwipeController(this));
+ } else {
+ boolean allowDragToOverview = SysUINavigationMode.INSTANCE.get(this)
+ .getMode().hasGestures;
+ list.add(new PortraitStatesTouchController(this, allowDragToOverview));
+ }
+ return list.toArray(new TouchController[list.size()]);
+ }
+}
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
deleted file mode 100644
index d5ea1ec..0000000
--- a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.graphics.RotationMode;
-import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
-import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController;
-import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
-import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
-import com.android.launcher3.util.TouchController;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.views.IconRecentsView;
-
-import java.util.ArrayList;
-
-/**
- * Provides recents-related {@link UiFactory} logic and classes.
- */
-public abstract class RecentsUiFactory {
-
- public static final boolean GO_LOW_RAM_RECENTS_ENABLED = true;
-
- public static TouchController[] createTouchControllers(Launcher launcher) {
- ArrayList<TouchController> list = new ArrayList<>();
- list.add(launcher.getDragController());
-
- if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- list.add(new LandscapeStatesTouchController(launcher));
- list.add(new LandscapeEdgeSwipeController(launcher));
- } else {
- boolean allowDragToOverview = SysUINavigationMode.INSTANCE.get(launcher)
- .getMode().hasGestures;
- list.add(new PortraitStatesTouchController(launcher, allowDragToOverview));
- }
- if (Utilities.IS_DEBUG_DEVICE
- && !launcher.getDeviceProfile().isMultiWindowMode
- && !launcher.getDeviceProfile().isVerticalBarLayout()) {
- list.add(new StatusBarTouchController(launcher));
- }
- return list.toArray(new TouchController[list.size()]);
- }
-
- /**
- * Creates and returns the controller responsible for recents view state transitions.
- *
- * @param launcher the launcher activity
- * @return state handler for recents
- */
- public static StateHandler createRecentsViewStateController(Launcher launcher) {
- return new RecentsViewStateController(launcher);
- }
-
- /**
- * Clean-up logic that occurs when recents is no longer in use/visible.
- *
- * @param launcher the launcher activity
- */
- public static void resetOverview(Launcher launcher) {
- IconRecentsView recentsView = launcher.getOverviewPanel();
- recentsView.setTransitionedFromApp(false);
- }
-
- /**
- * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
- *
- * @param launcher the launcher activity
- */
- public static void onLauncherStateOrResumeChanged(Launcher launcher) {}
-
- public static RotationMode getRotationMode(DeviceProfile dp) {
- return RotationMode.NORMAL;
- }
-}
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
new file mode 100644
index 0000000..60afddb
--- /dev/null
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2019, 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.
+*/
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.launcher3">
+ <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
+ <!--
+ Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
+ Refer comments around specific entries on how to extend individual components.
+ -->
+
+ <application
+ android:backupAgent="com.android.launcher3.LauncherBackupAgent"
+ android:fullBackupOnly="true"
+ android:fullBackupContent="@xml/backupscheme"
+ android:hardwareAccelerated="true"
+ android:icon="@drawable/ic_launcher_home"
+ android:label="@string/derived_app_name"
+ android:theme="@style/AppTheme"
+ android:largeHeap="@bool/config_largeHeap"
+ android:restoreAnyVersion="true"
+ android:supportsRtl="true" >
+
+ <!--
+ Main launcher activity. When extending only change the name, and keep all the
+ attributes and intent filters the same
+ -->
+ <activity
+ android:name="com.android.launcher3.uioverrides.QuickstepLauncher"
+ android:launchMode="singleTask"
+ android:clearTaskOnLaunch="true"
+ android:stateNotNeeded="true"
+ android:windowSoftInputMode="adjustPan"
+ android:screenOrientation="unspecified"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
+ android:resizeableActivity="true"
+ android:resumeWhilePausing="true"
+ android:taskAffinity=""
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.HOME" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.MONKEY"/>
+ <category android:name="android.intent.category.LAUNCHER_APP" />
+ </intent-filter>
+ <meta-data
+ android:name="com.android.launcher3.grid.control"
+ android:value="${packageName}.grid_control" />
+ </activity>
+
+ </application>
+</manifest>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
similarity index 76%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
rename to quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 2a22e9d..43cdbdb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -1,4 +1,4 @@
-/*
+/**
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -21,13 +20,14 @@
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.view.Gravity;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
@@ -49,21 +49,15 @@
import java.util.ArrayList;
-/**
- * Provides recents-related {@link UiFactory} logic and classes.
- */
-public abstract class RecentsUiFactory {
-
- private static final String TAG = RecentsUiFactory.class.getSimpleName();
+public class QuickstepLauncher extends BaseQuickstepLauncher {
public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false;
/**
* Reusable command for applying the shelf height on the background thread.
*/
- public static final AsyncCommand SET_SHELF_HEIGHT = (context, arg1, arg2) -> {
- SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2);
- };
+ public static final AsyncCommand SET_SHELF_HEIGHT = (context, arg1, arg2) ->
+ SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2);
public static RotationMode ROTATION_LANDSCAPE = new RotationMode(-90) {
@Override
@@ -138,71 +132,78 @@
}
};
- public static RotationMode getRotationMode(DeviceProfile dp) {
+ @Override
+ protected RotationMode getFakeRotationMode(DeviceProfile dp) {
return !dp.isVerticalBarLayout() ? RotationMode.NORMAL
: (dp.isSeascape() ? ROTATION_SEASCAPE : ROTATION_LANDSCAPE);
}
- public static TouchController[] createTouchControllers(Launcher launcher) {
- Mode mode = SysUINavigationMode.getMode(launcher);
-
- ArrayList<TouchController> list = new ArrayList<>();
- list.add(launcher.getDragController());
- if (mode == NO_BUTTON) {
- list.add(new QuickSwitchTouchController(launcher));
- list.add(new NavBarToHomeTouchController(launcher));
- list.add(new FlingAndHoldTouchController(launcher));
- } else {
- if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- list.add(new OverviewToAllAppsTouchController(launcher));
- list.add(new LandscapeEdgeSwipeController(launcher));
- if (mode.hasGestures) {
- list.add(new TransposedQuickSwitchTouchController(launcher));
- }
- } else {
- list.add(new PortraitStatesTouchController(launcher,
- mode.hasGestures /* allowDragToOverview */));
- if (mode.hasGestures) {
- list.add(new QuickSwitchTouchController(launcher));
- }
- }
- }
-
- if (!launcher.getDeviceProfile().isMultiWindowMode) {
- list.add(new StatusBarTouchController(launcher));
- }
-
- list.add(new LauncherTaskViewController(launcher));
- return list.toArray(new TouchController[list.size()]);
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ onStateOrResumeChanged();
}
- /**
- * Creates and returns the controller responsible for recents view state transitions.
- *
- * @param launcher the launcher activity
- * @return state handler for recents
- */
- public static StateHandler createRecentsViewStateController(Launcher launcher) {
- return new RecentsViewStateController(launcher);
+ @Override
+ protected void onActivityFlagsChanged(int changeBits) {
+ super.onActivityFlagsChanged(changeBits);
+
+ if ((changeBits & (ACTIVITY_STATE_DEFERRED_RESUMED | ACTIVITY_STATE_STARTED
+ | ACTIVITY_STATE_USER_ACTIVE | ACTIVITY_STATE_TRANSITION_ACTIVE)) != 0
+ && (getActivityFlags() & ACTIVITY_STATE_TRANSITION_ACTIVE) == 0) {
+ onStateOrResumeChanged();
+ }
}
/**
* Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
- *
- * @param launcher the launcher activity
*/
- public static void onLauncherStateOrResumeChanged(Launcher launcher) {
- LauncherState state = launcher.getStateManager().getState();
- DeviceProfile profile = launcher.getDeviceProfile();
- boolean visible = (state == NORMAL || state == OVERVIEW) && launcher.isUserActive()
+ private void onStateOrResumeChanged() {
+ LauncherState state = getStateManager().getState();
+ DeviceProfile profile = getDeviceProfile();
+ boolean visible = (state == NORMAL || state == OVERVIEW) && isUserActive()
&& !profile.isVerticalBarLayout();
- UiThreadHelper.runAsyncCommand(launcher, SET_SHELF_HEIGHT, visible ? 1 : 0,
+ UiThreadHelper.runAsyncCommand(this, SET_SHELF_HEIGHT, visible ? 1 : 0,
profile.hotseatBarSizePx);
if (state == NORMAL) {
- launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
+ ((RecentsView) getOverviewPanel()).setSwipeDownShouldLaunchApp(false);
}
}
+ @Override
+ public TouchController[] createTouchControllers() {
+ Mode mode = SysUINavigationMode.getMode(this);
+
+ ArrayList<TouchController> list = new ArrayList<>();
+ list.add(getDragController());
+ if (mode == NO_BUTTON) {
+ list.add(new QuickSwitchTouchController(this));
+ list.add(new NavBarToHomeTouchController(this));
+ list.add(new FlingAndHoldTouchController(this));
+ } else {
+ if (getDeviceProfile().isVerticalBarLayout()) {
+ list.add(new OverviewToAllAppsTouchController(this));
+ list.add(new LandscapeEdgeSwipeController(this));
+ if (mode.hasGestures) {
+ list.add(new TransposedQuickSwitchTouchController(this));
+ }
+ } else {
+ list.add(new PortraitStatesTouchController(this,
+ mode.hasGestures /* allowDragToOverview */));
+ if (mode.hasGestures) {
+ list.add(new QuickSwitchTouchController(this));
+ }
+ }
+ }
+
+ if (!getDeviceProfile().isMultiWindowMode) {
+ list.add(new StatusBarTouchController(this));
+ }
+
+ list.add(new LauncherTaskViewController(this));
+ return list.toArray(new TouchController[list.size()]);
+ }
+
private static final class LauncherTaskViewController extends
TaskViewTouchController<Launcher> {
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/util/NavBarPosition.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
index bbb318a..e2524b1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep.util;
-import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE;
-import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
+import static com.android.launcher3.uioverrides.QuickstepLauncher.ROTATION_LANDSCAPE;
+import static com.android.launcher3.uioverrides.QuickstepLauncher.ROTATION_SEASCAPE;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import android.content.Context;
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/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
new file mode 100644
index 0000000..f55ef94
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3;
+
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.allapps.DiscoveryBounce.BOUNCE_MAX_COUNT;
+import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_COUNT;
+import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
+import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_COUNT;
+import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
+
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+
+import com.android.launcher3.LauncherState.ScaleAndTranslation;
+import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.proxy.ProxyActivityStarter;
+import com.android.launcher3.proxy.StartActivityParams;
+import com.android.launcher3.uioverrides.BackButtonAlphaHandler;
+import com.android.launcher3.uioverrides.RecentsViewStateController;
+import com.android.launcher3.util.UiThreadHelper;
+import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
+import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.RemoteFadeOutAnimationListener;
+
+/**
+ * Extension of Launcher activity to provide quickstep specific functionality
+ */
+public abstract class BaseQuickstepLauncher extends Launcher
+ implements NavigationModeChangeListener {
+
+ /**
+ * Reusable command for applying the back button alpha on the background thread.
+ */
+ public static final UiThreadHelper.AsyncCommand SET_BACK_BUTTON_ALPHA =
+ (context, arg1, arg2) -> SystemUiProxy.INSTANCE.get(context).setBackButtonAlpha(
+ Float.intBitsToFloat(arg1), arg2 != 0);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ SysUINavigationMode.Mode mode = SysUINavigationMode.INSTANCE.get(this)
+ .addModeChangeListener(this);
+ getRotationHelper().setRotationHadDifferentUI(mode != Mode.NO_BUTTON);
+
+ if (!getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
+ getStateManager().addStateListener(new LauncherStateManager.StateListener() {
+ @Override
+ public void onStateTransitionStart(LauncherState toState) { }
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ boolean swipeUpEnabled = SysUINavigationMode.INSTANCE
+ .get(BaseQuickstepLauncher.this).getMode().hasGestures;
+ LauncherState prevState = getStateManager().getLastState();
+
+ if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
+ && finalState == ALL_APPS && prevState == NORMAL) || BOUNCE_MAX_COUNT
+ <= getSharedPrefs().getInt(HOME_BOUNCE_COUNT, 0))) {
+ getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
+ getStateManager().removeStateListener(this);
+ }
+ }
+ });
+ }
+
+ if (!getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)) {
+ getStateManager().addStateListener(new LauncherStateManager.StateListener() {
+ @Override
+ public void onStateTransitionStart(LauncherState toState) { }
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ LauncherState prevState = getStateManager().getLastState();
+
+ if ((finalState == ALL_APPS && prevState == OVERVIEW) || BOUNCE_MAX_COUNT
+ <= getSharedPrefs().getInt(SHELF_BOUNCE_COUNT, 0)) {
+ getSharedPrefs().edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
+ getStateManager().removeStateListener(this);
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onNavigationModeChanged(Mode newMode) {
+ getDragLayer().recreateControllers();
+ getRotationHelper().setRotationHadDifferentUI(newMode != Mode.NO_BUTTON);
+ }
+
+ @Override
+ public void onEnterAnimationComplete() {
+ super.onEnterAnimationComplete();
+ // After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
+ // as a part of quickstep, so that high-res thumbnails can load the next time we enter
+ // overview
+ RecentsModel.INSTANCE.get(this).getThumbnailCache()
+ .getHighResLoadingState().setVisible(true);
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+ RecentsModel.INSTANCE.get(this).onTrimMemory(level);
+ }
+
+ @Override
+ public void startIntentSenderForResult(IntentSender intent, int requestCode,
+ Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
+ if (requestCode != -1) {
+ mPendingActivityRequestCode = requestCode;
+ StartActivityParams params = new StartActivityParams(this, requestCode);
+ params.intentSender = intent;
+ params.fillInIntent = fillInIntent;
+ params.flagsMask = flagsMask;
+ params.flagsValues = flagsValues;
+ params.extraFlags = extraFlags;
+ params.options = options;
+ startActivity(ProxyActivityStarter.getLaunchIntent(this, params));
+ } else {
+ super.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask,
+ flagsValues, extraFlags, options);
+ }
+ }
+
+ @Override
+ public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
+ if (requestCode != -1) {
+ mPendingActivityRequestCode = -1;
+ StartActivityParams params = new StartActivityParams(this, requestCode);
+ params.intent = intent;
+ params.options = options;
+ startActivity(ProxyActivityStarter.getLaunchIntent(this, params));
+ } else {
+ super.startActivityForResult(intent, requestCode, options);
+ }
+ }
+
+ @Override
+ protected void onDeferredResumed() {
+ if (mPendingActivityRequestCode != -1 && isInState(NORMAL)) {
+ // Remove any active ProxyActivityStarter task and send RESULT_CANCELED to Launcher.
+ onActivityResult(mPendingActivityRequestCode, RESULT_CANCELED, null);
+ // ProxyActivityStarter is started with clear task to reset the task after which it
+ // removes the task itself.
+ startActivity(ProxyActivityStarter.getLaunchIntent(this, null));
+ }
+ }
+
+ @Override
+ protected StateHandler[] createStateHandlers() {
+ return new StateHandler[] {
+ getAllAppsController(),
+ getWorkspace(),
+ new RecentsViewStateController(this),
+ new BackButtonAlphaHandler(this)};
+ }
+
+ @Override
+ protected ScaleAndTranslation getOverviewScaleAndTranslationForNormalState() {
+ if (SysUINavigationMode.getMode(this) == Mode.NO_BUTTON) {
+ float offscreenTranslationX = getDeviceProfile().widthPx
+ - getOverviewPanel().getPaddingStart();
+ return new ScaleAndTranslation(1f, offscreenTranslationX, 0f);
+ }
+ return super.getOverviewScaleAndTranslationForNormalState();
+ }
+
+ @Override
+ public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
+ QuickstepAppTransitionManagerImpl appTransitionManager =
+ (QuickstepAppTransitionManagerImpl) getAppTransitionManager();
+ appTransitionManager.setRemoteAnimationProvider((appTargets, wallpaperTargets) -> {
+
+ // On the first call clear the reference.
+ signal.cancel();
+
+ ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
+ fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
+ wallpaperTargets));
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(fadeAnimation);
+ return anim;
+ }, signal);
+ }
+
+ @Override
+ public void onDragLayerHierarchyChanged() {
+ onLauncherStateOrFocusChanged();
+ }
+
+ @Override
+ protected void onActivityFlagsChanged(int changeBits) {
+ if ((changeBits
+ & (ACTIVITY_STATE_WINDOW_FOCUSED | ACTIVITY_STATE_TRANSITION_ACTIVE)) != 0) {
+ onLauncherStateOrFocusChanged();
+ }
+
+ super.onActivityFlagsChanged(changeBits);
+ }
+
+ /**
+ * Sets the back button visibility based on the current state/window focus.
+ */
+ private void onLauncherStateOrFocusChanged() {
+ Mode mode = SysUINavigationMode.getMode(this);
+ boolean shouldBackButtonBeHidden = mode.hasGestures
+ && getStateManager().getState().hideBackButton
+ && hasWindowFocus()
+ && (getActivityFlags() & ACTIVITY_STATE_TRANSITION_ACTIVE) == 0;
+ if (shouldBackButtonBeHidden) {
+ // Show the back button if there is a floating view visible.
+ shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenViewWithType(this,
+ TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null;
+ }
+ UiThreadHelper.setBackButtonAlphaAsync(this, SET_BACK_BUTTON_ALPHA,
+ shouldBackButtonBeHidden ? 0f : 1f, true /* animate */);
+ if (getDragLayer() != null) {
+ getRootView().setDisallowBackGesture(shouldBackButtonBeHidden);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
new file mode 100644
index 0000000..965b5f0
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import android.app.Activity;
+import android.app.Person;
+import android.content.pm.ShortcutInfo;
+import android.util.Base64;
+
+import com.android.launcher3.Utilities;
+import com.android.systemui.shared.system.ActivityCompat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.zip.Deflater;
+
+public class ApiWrapper {
+
+ public static boolean dumpActivity(Activity activity, PrintWriter writer) {
+ if (!Utilities.IS_DEBUG_DEVICE) {
+ return false;
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (!(new ActivityCompat(activity).encodeViewHierarchy(out))) {
+ return false;
+ }
+
+ Deflater deflater = new Deflater();
+ deflater.setInput(out.toByteArray());
+ deflater.finish();
+
+ out.reset();
+ byte[] buffer = new byte[1024];
+ while (!deflater.finished()) {
+ int count = deflater.deflate(buffer); // returns the generated code... index
+ out.write(buffer, 0, count);
+ }
+
+ writer.println("--encoded-view-dump-v0--");
+ writer.println(Base64.encodeToString(
+ out.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING));
+ return true;
+ }
+
+ public static Person[] getPersons(ShortcutInfo si) {
+ Person[] persons = si.getPersons();
+ return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java b/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
index aa0dfc3..43dc882 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
@@ -16,11 +16,9 @@
package com.android.launcher3.uioverrides;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.anim.AnimatorSetBuilder;
@@ -30,18 +28,14 @@
public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler {
- private static final String TAG = "BackButtonAlphaHandler";
+ private final BaseQuickstepLauncher mLauncher;
- private final Launcher mLauncher;
-
- public BackButtonAlphaHandler(Launcher launcher) {
+ public BackButtonAlphaHandler(BaseQuickstepLauncher launcher) {
mLauncher = launcher;
}
@Override
- public void setState(LauncherState state) {
- UiFactory.onLauncherStateOrFocusChanged(mLauncher);
- }
+ public void setState(LauncherState state) { }
@Override
public void setStateWithAnimation(LauncherState toState,
@@ -52,8 +46,8 @@
if (!SysUINavigationMode.getMode(mLauncher).hasGestures) {
// If the nav mode is not gestural, then force back button alpha to be 1
- UiThreadHelper.setBackButtonAlphaAsync(mLauncher, UiFactory.SET_BACK_BUTTON_ALPHA, 1f,
- true /* animate */);
+ UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
+ BaseQuickstepLauncher.SET_BACK_BUTTON_ALPHA, 1f, true /* animate */);
return;
}
@@ -64,15 +58,8 @@
anim.setDuration(config.duration);
anim.addUpdateListener(valueAnimator -> {
final float alpha = (float) valueAnimator.getAnimatedValue();
- UiThreadHelper.setBackButtonAlphaAsync(mLauncher, UiFactory.SET_BACK_BUTTON_ALPHA,
- alpha, false /* animate */);
- });
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // Reapply the final alpha in case some state (e.g. window focus) changed.
- UiFactory.onLauncherStateOrFocusChanged(mLauncher);
- }
+ UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
+ BaseQuickstepLauncher.SET_BACK_BUTTON_ALPHA, alpha, false /* animate */);
});
builder.play(anim);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
deleted file mode 100644
index 17c681b..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import static android.app.Activity.RESULT_CANCELED;
-
-import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
-import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
-import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.allapps.DiscoveryBounce.BOUNCE_MAX_COUNT;
-import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_COUNT;
-import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
-import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_COUNT;
-import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
-
-import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
-import android.app.Activity;
-import android.app.Person;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentSender;
-import android.content.pm.ShortcutInfo;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.util.Base64;
-
-import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherState.ScaleAndTranslation;
-import com.android.launcher3.LauncherStateManager;
-import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.QuickstepAppTransitionManagerImpl;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.proxy.ProxyActivityStarter;
-import com.android.launcher3.proxy.StartActivityParams;
-import com.android.launcher3.util.UiThreadHelper;
-import com.android.quickstep.RecentsModel;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
-import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.util.RemoteFadeOutAnimationListener;
-import com.android.systemui.shared.system.ActivityCompat;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-import java.util.zip.Deflater;
-
-public class UiFactory extends RecentsUiFactory {
-
- /**
- * Reusable command for applying the back button alpha on the background thread.
- */
- public static final UiThreadHelper.AsyncCommand SET_BACK_BUTTON_ALPHA =
- (context, arg1, arg2) -> {
- SystemUiProxy.INSTANCE.get(context).setBackButtonAlpha(Float.intBitsToFloat(arg1),
- arg2 != 0);
- };
-
- public static Runnable enableLiveUIChanges(Launcher launcher) {
- NavigationModeChangeListener listener = m -> {
- launcher.getDragLayer().recreateControllers();
- launcher.getRotationHelper().setRotationHadDifferentUI(m != Mode.NO_BUTTON);
- };
- SysUINavigationMode mode = SysUINavigationMode.INSTANCE.get(launcher);
- SysUINavigationMode.Mode m = mode.addModeChangeListener(listener);
- launcher.getRotationHelper().setRotationHadDifferentUI(m != Mode.NO_BUTTON);
- return () -> mode.removeModeChangeListener(listener);
- }
-
- public static StateHandler[] getStateHandler(Launcher launcher) {
- return new StateHandler[] {
- launcher.getAllAppsController(),
- launcher.getWorkspace(),
- createRecentsViewStateController(launcher),
- new BackButtonAlphaHandler(launcher)};
- }
-
- /**
- * Sets the back button visibility based on the current state/window focus.
- */
- public static void onLauncherStateOrFocusChanged(Launcher launcher) {
- Mode mode = SysUINavigationMode.getMode(launcher);
- boolean shouldBackButtonBeHidden = mode.hasGestures
- && launcher != null
- && launcher.getStateManager().getState().hideBackButton
- && launcher.hasWindowFocus();
- if (shouldBackButtonBeHidden) {
- // Show the back button if there is a floating view visible.
- shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenViewWithType(launcher,
- TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null;
- }
- UiThreadHelper.setBackButtonAlphaAsync(launcher, UiFactory.SET_BACK_BUTTON_ALPHA,
- shouldBackButtonBeHidden ? 0f : 1f, true /* animate */);
- if (launcher != null && launcher.getDragLayer() != null) {
- launcher.getRootView().setDisallowBackGesture(shouldBackButtonBeHidden);
- }
- }
-
- public static void onCreate(Launcher launcher) {
- if (!launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
- launcher.getStateManager().addStateListener(new LauncherStateManager.StateListener() {
- @Override
- public void onStateTransitionStart(LauncherState toState) {
- }
-
- @Override
- public void onStateTransitionComplete(LauncherState finalState) {
- boolean swipeUpEnabled = SysUINavigationMode.INSTANCE.get(launcher).getMode()
- .hasGestures;
- LauncherState prevState = launcher.getStateManager().getLastState();
-
- if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
- && finalState == ALL_APPS && prevState == NORMAL) || BOUNCE_MAX_COUNT <=
- launcher.getSharedPrefs().getInt(HOME_BOUNCE_COUNT, 0))) {
- launcher.getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
- launcher.getStateManager().removeStateListener(this);
- }
- }
- });
- }
-
- if (!launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)) {
- launcher.getStateManager().addStateListener(new LauncherStateManager.StateListener() {
- @Override
- public void onStateTransitionStart(LauncherState toState) {
- }
-
- @Override
- public void onStateTransitionComplete(LauncherState finalState) {
- LauncherState prevState = launcher.getStateManager().getLastState();
-
- if ((finalState == ALL_APPS && prevState == OVERVIEW) || BOUNCE_MAX_COUNT <=
- launcher.getSharedPrefs().getInt(SHELF_BOUNCE_COUNT, 0)) {
- launcher.getSharedPrefs().edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
- launcher.getStateManager().removeStateListener(this);
- }
- }
- });
- }
- }
-
- public static void onEnterAnimationComplete(Context context) {
- // After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
- // as a part of quickstep, so that high-res thumbnails can load the next time we enter
- // overview
- RecentsModel.INSTANCE.get(context).getThumbnailCache()
- .getHighResLoadingState().setVisible(true);
- }
-
- public static void onTrimMemory(Context context, int level) {
- RecentsModel model = RecentsModel.INSTANCE.get(context);
- if (model != null) {
- model.onTrimMemory(level);
- }
- }
-
- public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
- CancellationSignal cancellationSignal) {
- QuickstepAppTransitionManagerImpl appTransitionManager =
- (QuickstepAppTransitionManagerImpl) launcher.getAppTransitionManager();
- appTransitionManager.setRemoteAnimationProvider((appTargets, wallpaperTargets) -> {
-
- // On the first call clear the reference.
- cancellationSignal.cancel();
-
- ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
- fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
- wallpaperTargets));
- AnimatorSet anim = new AnimatorSet();
- anim.play(fadeAnimation);
- return anim;
- }, cancellationSignal);
- }
-
- public static boolean dumpActivity(Activity activity, PrintWriter writer) {
- if (!Utilities.IS_DEBUG_DEVICE) {
- return false;
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- if (!(new ActivityCompat(activity).encodeViewHierarchy(out))) {
- return false;
- }
-
- Deflater deflater = new Deflater();
- deflater.setInput(out.toByteArray());
- deflater.finish();
-
- out.reset();
- byte[] buffer = new byte[1024];
- while (!deflater.finished()) {
- int count = deflater.deflate(buffer); // returns the generated code... index
- out.write(buffer, 0, count);
- }
-
- writer.println("--encoded-view-dump-v0--");
- writer.println(Base64.encodeToString(
- out.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING));
- return true;
- }
-
- public static boolean startIntentSenderForResult(Activity activity, IntentSender intent,
- int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
- Bundle options) {
- StartActivityParams params = new StartActivityParams(activity, requestCode);
- params.intentSender = intent;
- params.fillInIntent = fillInIntent;
- params.flagsMask = flagsMask;
- params.flagsValues = flagsValues;
- params.extraFlags = extraFlags;
- params.options = options;
- ((Context) activity).startActivity(ProxyActivityStarter.getLaunchIntent(activity, params));
- return true;
- }
-
- public static boolean startActivityForResult(Activity activity, Intent intent, int requestCode,
- Bundle options) {
- StartActivityParams params = new StartActivityParams(activity, requestCode);
- params.intent = intent;
- params.options = options;
- activity.startActivity(ProxyActivityStarter.getLaunchIntent(activity, params));
- return true;
- }
-
- /**
- * Removes any active ProxyActivityStarter task and sends RESULT_CANCELED to Launcher.
- *
- * ProxyActivityStarter is started with clear task to reset the task after which it removes the
- * task itself.
- */
- public static void resetPendingActivityResults(Launcher launcher, int requestCode) {
- launcher.onActivityResult(requestCode, RESULT_CANCELED, null);
- launcher.startActivity(ProxyActivityStarter.getLaunchIntent(launcher, null));
- }
-
- public static ScaleAndTranslation getOverviewScaleAndTranslationForNormalState(Launcher l) {
- if (SysUINavigationMode.getMode(l) == Mode.NO_BUTTON) {
- float offscreenTranslationX = l.getDeviceProfile().widthPx
- - l.getOverviewPanel().getPaddingStart();
- return new ScaleAndTranslation(1f, offscreenTranslationX, 0f);
- }
- return new ScaleAndTranslation(1.1f, 0f, 0f);
- }
-
- public static Person[] getPersons(ShortcutInfo si) {
- Person[] persons = si.getPersons();
- return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
index 71833ad..5fcdc19 100644
--- a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java
@@ -27,7 +27,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
@@ -122,13 +121,17 @@
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
- UiFactory.onEnterAnimationComplete(this);
+ // After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
+ // as a part of quickstep, so that high-res thumbnails can load the next time we enter
+ // overview
+ RecentsModel.INSTANCE.get(this).getThumbnailCache()
+ .getHighResLoadingState().setVisible(true);
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
- UiFactory.onTrimMemory(this, level);
+ RecentsModel.INSTANCE.get(this).onTrimMemory(level);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 289a129..4f7d53b 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -15,7 +15,7 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.uioverrides.RecentsUiFactory.GO_LOW_RAM_RECENTS_ENABLED;
+import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.ComponentName;
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index b17ed4c..13731b6 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -31,6 +31,9 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
+import static com.android.launcher3.util.rule.TestStabilityRule.RUN_FLAFOR;
+import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_PRESUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -99,7 +102,7 @@
}
mOrderSensitiveRules = RuleChain.outerRule(new NavigationModeSwitchRule(mLauncher))
- .around(new FailureWatcher(mDevice));
+ .around(new FailureWatcher(mDevice));
mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
getHomeIntentInPackage(context),
@@ -131,7 +134,8 @@
@Test
public void goToOverviewFromHome() {
// b/142828227
- if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess()) {
+ if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
+ (RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
}
mDevice.pressHome();
@@ -145,7 +149,8 @@
@Test
public void goToOverviewFromApp() {
// b/142828227
- if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess()) {
+ if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
+ (RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
}
startAppFastAndWaitForRecentTask(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
@@ -183,7 +188,8 @@
@Test
public void testOverview() {
// b/142828227
- if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess()) {
+ if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
+ (RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
}
startAppFastAndWaitForRecentTask(getAppPackageName());
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index 25224b0..50cab74 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -18,6 +18,9 @@
import static com.android.launcher3.util.RaceConditionReproducer.enterEvt;
import static com.android.launcher3.util.RaceConditionReproducer.exitEvt;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
+import static com.android.launcher3.util.rule.TestStabilityRule.RUN_FLAFOR;
+import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_PRESUBMIT;
import android.content.Intent;
@@ -93,7 +96,8 @@
@NavigationModeSwitch
public void testStressSwipeToOverview() {
// b/142828227
- if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess()) {
+ if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
+ (RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
}
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index b28077f..382bfdf 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -35,7 +35,7 @@
import com.android.launcher3.logging.StatsLogUtils.LogStateProvider;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.logging.UserEventDispatcher.UserEventDelegate;
-import com.android.launcher3.uioverrides.UiFactory;
+import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.ViewCache;
@@ -81,19 +81,39 @@
protected StatsLogManager mStatsLogManager;
protected SystemUiController mSystemUiController;
- private static final int ACTIVITY_STATE_STARTED = 1 << 0;
- private static final int ACTIVITY_STATE_RESUMED = 1 << 1;
+
+ public static final int ACTIVITY_STATE_STARTED = 1 << 0;
+ public static final int ACTIVITY_STATE_RESUMED = 1 << 1;
+
/**
- * State flag indicating if the user is active or the actitvity when to background as a result
+ * State flags indicating that the activity has received one frame after resume, and was
+ * not immediately paused.
+ */
+ public static final int ACTIVITY_STATE_DEFERRED_RESUMED = 1 << 2;
+
+ public static final int ACTIVITY_STATE_WINDOW_FOCUSED = 1 << 3;
+
+ /**
+ * State flag indicating if the user is active or the activity when to background as a result
* of user action.
* @see #isUserActive()
*/
- private static final int ACTIVITY_STATE_USER_ACTIVE = 1 << 2;
+ public static final int ACTIVITY_STATE_USER_ACTIVE = 1 << 4;
+
+ /**
+ * State flag indicating that a state transition is in progress
+ */
+ public static final int ACTIVITY_STATE_TRANSITION_ACTIVE = 1 << 5;
@Retention(SOURCE)
@IntDef(
flag = true,
- value = {ACTIVITY_STATE_STARTED, ACTIVITY_STATE_RESUMED, ACTIVITY_STATE_USER_ACTIVE})
+ value = {ACTIVITY_STATE_STARTED,
+ ACTIVITY_STATE_RESUMED,
+ ACTIVITY_STATE_DEFERRED_RESUMED,
+ ACTIVITY_STATE_WINDOW_FOCUSED,
+ ACTIVITY_STATE_USER_ACTIVE,
+ ACTIVITY_STATE_TRANSITION_ACTIVE})
public @interface ActivityFlags{}
@ActivityFlags
@@ -146,19 +166,19 @@
@Override
protected void onStart() {
- mActivityFlags |= ACTIVITY_STATE_STARTED;
+ addActivityFlags(ACTIVITY_STATE_STARTED);
super.onStart();
}
@Override
protected void onResume() {
- mActivityFlags |= ACTIVITY_STATE_RESUMED | ACTIVITY_STATE_USER_ACTIVE;
+ addActivityFlags(ACTIVITY_STATE_RESUMED | ACTIVITY_STATE_USER_ACTIVE);
super.onResume();
}
@Override
protected void onUserLeaveHint() {
- mActivityFlags &= ~ACTIVITY_STATE_USER_ACTIVE;
+ removeActivityFlags(ACTIVITY_STATE_USER_ACTIVE);
super.onUserLeaveHint();
}
@@ -172,7 +192,7 @@
@Override
protected void onStop() {
- mActivityFlags &= ~ACTIVITY_STATE_STARTED & ~ACTIVITY_STATE_USER_ACTIVE;
+ removeActivityFlags(ACTIVITY_STATE_STARTED | ACTIVITY_STATE_USER_ACTIVE);
mForceInvisible = 0;
super.onStop();
@@ -183,7 +203,7 @@
@Override
protected void onPause() {
- mActivityFlags &= ~ACTIVITY_STATE_RESUMED;
+ removeActivityFlags(ACTIVITY_STATE_RESUMED | ACTIVITY_STATE_DEFERRED_RESUMED);
super.onPause();
// Reset the overridden sysui flags used for the task-swipe launch animation, we do this
@@ -193,6 +213,17 @@
getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
}
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (hasFocus) {
+ addActivityFlags(ACTIVITY_STATE_WINDOW_FOCUSED);
+ } else {
+ removeActivityFlags(ACTIVITY_STATE_WINDOW_FOCUSED);
+ }
+
+ }
+
public boolean isStarted() {
return (mActivityFlags & ACTIVITY_STATE_STARTED) != 0;
}
@@ -208,6 +239,22 @@
return (mActivityFlags & ACTIVITY_STATE_USER_ACTIVE) != 0;
}
+ public int getActivityFlags() {
+ return mActivityFlags;
+ }
+
+ protected void addActivityFlags(int flags) {
+ mActivityFlags |= flags;
+ onActivityFlagsChanged(flags);
+ }
+
+ protected void removeActivityFlags(int flags) {
+ mActivityFlags &= ~flags;
+ onActivityFlagsChanged(flags);
+ }
+
+ protected void onActivityFlagsChanged(int changeBits) { }
+
public void addOnDeviceProfileChangeListener(OnDeviceProfileChangeListener listener) {
mDPChangeListeners.add(listener);
}
@@ -233,7 +280,7 @@
/**
* Used to set the override visibility state, used only to handle the transition home with the
* recents animation.
- * @see QuickstepAppTransitionManagerImpl#getWallpaperOpenRunner()
+ * @see QuickstepAppTransitionManagerImpl#getWallpaperOpenRunner
*/
public void addForceInvisibleFlag(@InvisibilityFlags int flag) {
mForceInvisible |= flag;
@@ -260,7 +307,7 @@
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
- if (!UiFactory.dumpActivity(this, writer)) {
+ if (!ApiWrapper.dumpActivity(this, writer)) {
super.dump(prefix, fd, writer, args);
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 67c1a04..bb08ba8 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -58,6 +58,7 @@
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Parcelable;
import android.os.Process;
@@ -82,6 +83,8 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.LauncherState.ScaleAndTranslation;
+import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsStore;
@@ -114,8 +117,8 @@
import com.android.launcher3.qsb.QsbContainerView;
import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.touch.AllAppsSwipeController;
import com.android.launcher3.touch.ItemClickHandler;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -135,6 +138,7 @@
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.ViewOnDrawExecutor;
@@ -294,12 +298,11 @@
*/
private PendingRequestArgs mPendingRequestArgs;
// Request id for any pending activity result
- private int mPendingActivityRequestCode = -1;
+ protected int mPendingActivityRequestCode = -1;
public ViewGroupFocusHelper mFocusHandler;
private RotationHelper mRotationHelper;
- private Runnable mCancelTouchController;
final Handler mHandler = new Handler();
private final Runnable mHandleDeferredResume = this::handleDeferredResume;
@@ -350,7 +353,6 @@
mDragController = new DragController(this);
mAllAppsController = new AllAppsTransitionController(this);
mStateManager = new LauncherStateManager(this);
- UiFactory.onCreate(this);
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
mAppWidgetHost = new LauncherAppWidgetHost(this,
@@ -474,7 +476,6 @@
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
- UiFactory.onEnterAnimationComplete(this);
mAllAppsController.highlightWorkTabIfNecessary();
mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
}
@@ -488,7 +489,6 @@
}
mOldConfig.setTo(newConfig);
- UiFactory.onLauncherStateOrResumeChanged(this);
super.onConfigurationChanged(newConfig);
}
@@ -504,7 +504,7 @@
public void reapplyUi() {
if (supportsFakeLandscapeUI()) {
mRotationMode = mStableDeviceProfile == null
- ? RotationMode.NORMAL : UiFactory.getRotationMode(mDeviceProfile);
+ ? RotationMode.NORMAL : getFakeRotationMode(mDeviceProfile);
}
getRootView().dispatchInsets();
getStateManager().reapplyState(true /* cancelCurrentAnimation */);
@@ -567,7 +567,7 @@
if (supportsFakeLandscapeUI() && mDeviceProfile.isVerticalBarLayout()) {
mStableDeviceProfile = mDeviceProfile.inv.portraitProfile;
- mRotationMode = UiFactory.getRotationMode(mDeviceProfile);
+ mRotationMode = getFakeRotationMode(mDeviceProfile);
} else {
mStableDeviceProfile = null;
mRotationMode = RotationMode.NORMAL;
@@ -933,8 +933,6 @@
NotificationListener.removeNotificationsChangedListener();
getStateManager().moveToRestState();
- UiFactory.onLauncherStateOrResumeChanged(this);
-
// Workaround for b/78520668, explicitly trim memory once UI is hidden
onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
}
@@ -957,7 +955,6 @@
logStopAndResume(Action.Command.RESUME);
getUserEventDispatcher().startSession();
- UiFactory.onLauncherStateOrResumeChanged(this);
AppLaunchTracker.INSTANCE.get(this).onReturnedToHome();
// Process any items that were added while Launcher was away.
@@ -972,15 +969,17 @@
DiscoveryBounce.showForHomeIfNeeded(this);
- if (mPendingActivityRequestCode != -1 && isInState(NORMAL)) {
- UiFactory.resetPendingActivityResults(this, mPendingActivityRequestCode);
- }
+ onDeferredResumed();
+ addActivityFlags(ACTIVITY_STATE_DEFERRED_RESUMED);
+
mDeferredResumePending = false;
} else {
mDeferredResumePending = true;
}
}
+ protected void onDeferredResumed() { }
+
private void logStopAndResume(int command) {
int containerType = mStateManager.getState().containerType;
if (containerType == ContainerType.WORKSPACE && mWorkspace != null) {
@@ -1034,12 +1033,14 @@
if (mDeferOverlayCallbacks) {
scheduleDeferredCheck();
}
+ addActivityFlags(ACTIVITY_STATE_TRANSITION_ACTIVE);
}
public void onStateSetEnd(LauncherState state) {
getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
getWorkspace().setClipChildren(!state.disablePageClipping);
finishAutoCancelActionMode();
+ removeActivityFlags(ACTIVITY_STATE_TRANSITION_ACTIVE);
}
@Override
@@ -1084,18 +1085,6 @@
}
}
- @Override
- protected void onUserLeaveHint() {
- super.onUserLeaveHint();
- UiFactory.onLauncherStateOrResumeChanged(this);
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- mStateManager.onWindowFocusChanged();
- }
-
class LauncherOverlayCallbacksImpl implements LauncherOverlayCallbacks {
public void onScrollChanged(float progress) {
@@ -1159,7 +1148,6 @@
// Setup the drag layer
mDragLayer.setup(mDragController, mWorkspace);
- mCancelTouchController = UiFactory.enableLiveUIChanges(this);
mWorkspace.setup(mDragController);
// Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
@@ -1537,11 +1525,6 @@
mWorkspace.removeFolderListeners();
PluginManagerWrapper.INSTANCE.get(this).removePluginListener(this);
- if (mCancelTouchController != null) {
- mCancelTouchController.run();
- mCancelTouchController = null;
- }
-
// Stop callbacks from LauncherModel
// It's possible to receive onDestroy after a new Launcher activity has
// been created. In this case, don't interfere with the new Launcher.
@@ -1577,10 +1560,7 @@
if (requestCode != -1) {
mPendingActivityRequestCode = requestCode;
}
- if (requestCode == -1
- || !UiFactory.startActivityForResult(this, intent, requestCode, options)) {
- super.startActivityForResult(intent, requestCode, options);
- }
+ super.startActivityForResult(intent, requestCode, options);
}
@Override
@@ -1589,14 +1569,11 @@
if (requestCode != -1) {
mPendingActivityRequestCode = requestCode;
}
- if (requestCode == -1 || !UiFactory.startIntentSenderForResult(this, intent, requestCode,
- fillInIntent, flagsMask, flagsValues, extraFlags, options)) {
- try {
- super.startIntentSenderForResult(intent, requestCode,
- fillInIntent, flagsMask, flagsValues, extraFlags, options);
- } catch (IntentSender.SendIntentException e) {
- throw new ActivityNotFoundException();
- }
+ try {
+ super.startIntentSenderForResult(intent, requestCode,
+ fillInIntent, flagsMask, flagsValues, extraFlags, options);
+ } catch (IntentSender.SendIntentException e) {
+ throw new ActivityNotFoundException();
}
}
@@ -1934,7 +1911,6 @@
// This clears all widget bitmaps from the widget tray
// TODO(hyunyoungs)
}
- UiFactory.onTrimMemory(this, level);
}
@Override
@@ -2653,16 +2629,36 @@
return super.onKeyUp(keyCode, event);
}
- public static Launcher getLauncher(Context context) {
- return (Launcher) fromContext(context);
+ protected StateHandler[] createStateHandlers() {
+ return new StateHandler[] { getAllAppsController(), getWorkspace() };
}
+ public TouchController[] createTouchControllers() {
+ return new TouchController[] {getDragController(), new AllAppsSwipeController(this)};
+ }
+
+ protected RotationMode getFakeRotationMode(DeviceProfile deviceProfile) {
+ return RotationMode.NORMAL;
+ }
+
+ protected ScaleAndTranslation getOverviewScaleAndTranslationForNormalState() {
+ return new ScaleAndTranslation(1.1f, 0f, 0f);
+ }
+
+ public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) { }
+
+ public void onDragLayerHierarchyChanged() { }
+
@Override
public void returnToHomescreen() {
super.returnToHomescreen();
getStateManager().goToState(LauncherState.NORMAL);
}
+ public static Launcher getLauncher(Context context) {
+ return (Launcher) fromContext(context);
+ }
+
/**
* Just a wrapper around the type cast to allow easier tracking of calls.
*/
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 6e2626b..d2b447b 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -26,9 +26,11 @@
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
+import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -36,14 +38,11 @@
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import android.view.animation.Interpolator;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.states.SpringLoadedState;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.uioverrides.states.AllAppsState;
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -210,7 +209,7 @@
}
public ScaleAndTranslation getOverviewScaleAndTranslation(Launcher launcher) {
- return UiFactory.getOverviewScaleAndTranslationForNormalState(launcher);
+ return launcher.getOverviewScaleAndTranslationForNormalState();
}
public float getOverviewFullscreenProgress() {
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 848e19f..daf270b 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -24,7 +24,8 @@
import android.animation.AnimatorSet;
import android.os.Handler;
import android.os.Looper;
-import android.util.Log;
+
+import androidx.annotation.IntDef;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -32,16 +33,12 @@
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter;
import com.android.launcher3.compat.AccessibilityManagerCompat;
-import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.uioverrides.UiFactory;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import androidx.annotation.IntDef;
-
/**
* TODO: figure out what kind of tests we can write for this
*
@@ -146,7 +143,7 @@
public StateHandler[] getStateHandlers() {
if (mStateHandlers == null) {
- mStateHandlers = UiFactory.getStateHandler(mLauncher);
+ mStateHandlers = mLauncher.createStateHandlers();
}
return mStateHandlers;
}
@@ -414,7 +411,6 @@
// Only disable clipping if needed, otherwise leave it as previous value.
mLauncher.getWorkspace().setClipChildren(false);
}
- UiFactory.onLauncherStateOrResumeChanged(mLauncher);
for (int i = mListeners.size() - 1; i >= 0; i--) {
mListeners.get(i).onStateTransitionStart(state);
@@ -435,8 +431,6 @@
setRestState(null);
}
- UiFactory.onLauncherStateOrResumeChanged(mLauncher);
-
for (int i = mListeners.size() - 1; i >= 0; i--) {
mListeners.get(i).onStateTransitionComplete(state);
}
@@ -444,10 +438,6 @@
AccessibilityManagerCompat.sendStateEventToTest(mLauncher, state.ordinal);
}
- public void onWindowFocusChanged() {
- UiFactory.onLauncherStateOrFocusChanged(mLauncher);
- }
-
public LauncherState getLastState() {
return mLastStableState;
}
diff --git a/src/com/android/launcher3/WorkspaceItemInfo.java b/src/com/android/launcher3/WorkspaceItemInfo.java
index 23795c5..71bd92f 100644
--- a/src/com/android/launcher3/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/WorkspaceItemInfo.java
@@ -28,7 +28,7 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.uioverrides.UiFactory;
+import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.ContentWriter;
import java.util.Arrays;
@@ -192,7 +192,7 @@
}
disabledMessage = shortcutInfo.getDisabledMessage();
- Person[] persons = UiFactory.getPersons(shortcutInfo);
+ Person[] persons = ApiWrapper.getPersons(shortcutInfo);
personKeys = persons.length == 0 ? Utilities.EMPTY_STRING_ARRAY
: Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new);
}
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index cdc7061..8823bde 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -57,7 +57,6 @@
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.views.Transposable;
@@ -121,7 +120,7 @@
}
public void recreateControllers() {
- mControllers = UiFactory.createTouchControllers(mActivity);
+ mControllers = mActivity.createTouchControllers();
}
public ViewGroupFocusHelper getFocusIndicatorHelper() {
@@ -477,14 +476,14 @@
public void onViewAdded(View child) {
super.onViewAdded(child);
updateChildIndices();
- UiFactory.onLauncherStateOrFocusChanged(mActivity);
+ mActivity.onDragLayerHierarchyChanged();
}
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
updateChildIndices();
- UiFactory.onLauncherStateOrFocusChanged(mActivity);
+ mActivity.onDragLayerHierarchyChanged();
}
@Override
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index 07eb0d6..869dd94 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -32,7 +32,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.PendingAddItemInfo;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -68,7 +67,7 @@
public boolean init(Launcher launcher, boolean alreadyOnHome) {
super.init(launcher, alreadyOnHome);
if (!alreadyOnHome) {
- UiFactory.useFadeOutAnimationForLauncherStart(launcher, mCancelSignal);
+ launcher.useFadeOutAnimationForLauncherStart(mCancelSignal);
}
return false;
}
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/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
similarity index 77%
rename from src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
rename to src/com/android/launcher3/touch/AllAppsSwipeController.java
index bd6ea50..195c7f0 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -1,4 +1,19 @@
-package com.android.launcher3.uioverrides;
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.touch;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -9,8 +24,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
-import com.android.launcher3.touch.AbstractStateChangeTouchController;
-import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
/**
@@ -58,8 +71,8 @@
@Override
protected int getLogContainerTypeForNormalState(MotionEvent ev) {
- return mLauncher.getDragLayer().isEventOverView(mLauncher.getHotseat(), mTouchDownEvent) ?
- ContainerType.HOTSEAT : ContainerType.WORKSPACE;
+ return mLauncher.getDragLayer().isEventOverView(mLauncher.getHotseat(), mTouchDownEvent)
+ ? ContainerType.HOTSEAT : ContainerType.WORKSPACE;
}
@Override
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index a133f01..ec87e79 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -23,7 +23,6 @@
import android.os.IBinder;
import android.os.Message;
import android.view.inputmethod.InputMethodManager;
-import com.android.launcher3.uioverrides.UiFactory;
/**
* Utility class for offloading some class from UI thread
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
new file mode 100644
index 0000000..5407ea3
--- /dev/null
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import android.app.Activity;
+import android.app.Person;
+import android.content.pm.ShortcutInfo;
+
+import com.android.launcher3.Utilities;
+
+import java.io.PrintWriter;
+
+public class ApiWrapper {
+
+ public static boolean dumpActivity(Activity activity, PrintWriter writer) {
+ return false;
+ }
+
+ public static Person[] getPersons(ShortcutInfo si) {
+ return Utilities.EMPTY_PERSON_ARRAY;
+ }
+}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
deleted file mode 100644
index 606c990..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import android.app.Activity;
-import android.app.Person;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentSender;
-import android.content.pm.ShortcutInfo;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState.ScaleAndTranslation;
-import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.graphics.RotationMode;
-import com.android.launcher3.util.TouchController;
-
-import java.io.PrintWriter;
-
-public class UiFactory {
-
- public static TouchController[] createTouchControllers(Launcher launcher) {
- return new TouchController[] {
- launcher.getDragController(), new AllAppsSwipeController(launcher)};
- }
-
- public static Runnable enableLiveUIChanges(Launcher l) {
- return null;
- }
-
- public static StateHandler[] getStateHandler(Launcher launcher) {
- return new StateHandler[] {
- launcher.getAllAppsController(), launcher.getWorkspace() };
- }
-
- public static void resetOverview(Launcher launcher) { }
-
- public static void onLauncherStateOrFocusChanged(Launcher launcher) { }
-
- public static void onCreate(Launcher launcher) { }
-
- public static void onStart(Launcher launcher) { }
-
- public static void onEnterAnimationComplete(Context context) {}
-
- public static void onLauncherStateOrResumeChanged(Launcher launcher) { }
-
- public static void onTrimMemory(Launcher launcher, int level) { }
-
- public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
- CancellationSignal cancellationSignal) { }
-
- public static boolean dumpActivity(Activity activity, PrintWriter writer) {
- return false;
- }
-
- public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) { }
-
-
- public static ScaleAndTranslation getOverviewScaleAndTranslationForNormalState(Launcher l) {
- return new ScaleAndTranslation(1.1f, 0f, 0f);
- }
-
- public static RotationMode getRotationMode(DeviceProfile dp) {
- return RotationMode.NORMAL;
- }
-
- public static boolean startIntentSenderForResult(Activity activity, IntentSender intent,
- int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
- Bundle options) {
- return false;
- }
-
- public static boolean startActivityForResult(Activity activity, Intent intent, int requestCode,
- Bundle options) {
- return false;
- }
-
- public static void resetPendingActivityResults(Launcher launcher, int requestCode) { }
-
- public static Person[] getPersons(ShortcutInfo si) {
- return Utilities.EMPTY_PERSON_ARRAY;
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 465cee2..29da0fa 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -18,6 +18,10 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
+import static com.android.launcher3.util.rule.TestStabilityRule.RUN_FLAFOR;
+import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_PRESUBMIT;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -174,7 +178,8 @@
@Test
public void testWorkspace() throws Exception {
// b/142828227
- if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess()) {
+ if (android.os.Build.MODEL.contains("Cuttlefish") && TestHelpers.isInLauncherProcess() &&
+ (RUN_FLAFOR & (PLATFORM_PRESUBMIT | UNBUNDLED_PRESUBMIT)) != 0) {
return;
}
final Workspace workspace = mLauncher.getWorkspace();
diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
index 69bf01d..08fa098 100644
--- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
@@ -57,7 +57,7 @@
public static final int PLATFORM_PRESUBMIT = 0x8;
public static final int PLATFORM_POSTSUBMIT = 0x10;
- private static final int RUN_FLAFOR = getRunFlavor();
+ public static final int RUN_FLAFOR = getRunFlavor();
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)