diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index e3fcd2f376..8d7a5343e8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -35,6 +35,7 @@ import android.app.ActivityManager.RunningTaskInfo; import android.app.Service; import android.app.TaskInfo; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -49,19 +50,18 @@ import android.view.InputEvent; import android.view.MotionEvent; import androidx.annotation.BinderThread; +import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.WorkerThread; import com.android.launcher3.BaseDraggingActivity; -import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.DiscoveryBounce; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.testing.TestProtocol; +import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener; @@ -70,12 +70,14 @@ import com.android.quickstep.inputconsumers.AssistantInputConsumer; import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer; import com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer; import com.android.quickstep.inputconsumers.OtherActivityInputConsumer; +import com.android.quickstep.inputconsumers.OverscrollInputConsumer; import com.android.quickstep.inputconsumers.OverviewInputConsumer; import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer; -import com.android.quickstep.inputconsumers.QuickCaptureInputConsumer; import com.android.quickstep.inputconsumers.ResetGestureInputConsumer; import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer; import com.android.quickstep.util.ActiveGestureLog; +import com.android.systemui.plugins.OverscrollPlugin; +import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -113,7 +115,7 @@ class ArgList extends LinkedList { */ @TargetApi(Build.VERSION_CODES.Q) public class TouchInteractionService extends Service implements - NavigationModeChangeListener { + NavigationModeChangeListener, PluginListener { private static final String TAG = "TouchInteractionService"; @@ -122,6 +124,8 @@ public class TouchInteractionService extends Service implements private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once"; private static final int MAX_BACK_NOTIFICATION_COUNT = 3; private int mBackGestureNotificationCounter = -1; + @Nullable + private OverscrollPlugin mOverscrollPlugin; private final IBinder mMyBinder = new IOverviewProxy.Stub() { @@ -280,6 +284,9 @@ public class TouchInteractionService extends Service implements onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this)); sConnected = true; + + PluginManagerWrapper.INSTANCE.get(getBaseContext()).addPluginListener(this, + OverscrollPlugin.class, false /* allowMultiple */); } private void disposeEventHandlers() { @@ -400,6 +407,9 @@ public class TouchInteractionService extends Service implements if (TestProtocol.sDebugTracing) { Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "TIS destroyed"); } + + PluginManagerWrapper.INSTANCE.get(getBaseContext()).removePluginListener(this); + sIsInitialized = false; if (mDeviceState.isUserUnlocked()) { mInputConsumer.unregisterInputConsumer(); @@ -489,10 +499,10 @@ public class TouchInteractionService extends Service implements base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat); } - if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) { - // Put the Compose gesture as higher priority than the Assistant or base gestures - base = new QuickCaptureInputConsumer(this, newGestureState, base, - mInputMonitorCompat); + if (mOverscrollPlugin != null) { + // Put the overscroll gesture as higher priority than the Assistant or base gestures + base = new OverscrollInputConsumer(this, newGestureState, base, mInputMonitorCompat, + mOverscrollPlugin); } if (mDeviceState.isScreenPinningActive()) { @@ -531,9 +541,9 @@ public class TouchInteractionService extends Service implements () -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT)); if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) { final ComponentName homeComponent = - mOverviewComponentObserver.getHomeIntent().getComponent(); + mOverviewComponentObserver.getHomeIntent().getComponent(); forceOverviewInputConsumer = - runningTaskInfo.baseIntent.getComponent(). equals(homeComponent); + runningTaskInfo.baseIntent.getComponent().equals(homeComponent); } } @@ -763,4 +773,14 @@ public class TouchInteractionService extends Service implements UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance() .startRecentsActivity(intent, null, listener, null, null)); } + + @Override + public void onPluginConnected(OverscrollPlugin overscrollPlugin, Context context) { + mOverscrollPlugin = overscrollPlugin; + } + + @Override + public void onPluginDisconnected(OverscrollPlugin overscrollPlugin) { + mOverscrollPlugin = null; + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/QuickCaptureInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java similarity index 74% rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/QuickCaptureInputConsumer.java rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java index 9826b3a043..e3da98b5ea 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/QuickCaptureInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java @@ -24,39 +24,28 @@ import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.Utilities.squaredHypot; -import android.app.ActivityOptions; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; import android.graphics.PointF; -import android.os.Bundle; import android.view.MotionEvent; import android.view.ViewConfiguration; +import androidx.annotation.Nullable; + import com.android.launcher3.BaseDraggingActivity; -import com.android.launcher3.R; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.views.RecentsView; +import com.android.systemui.plugins.OverscrollPlugin; import com.android.systemui.shared.system.InputMonitorCompat; /** - * Input consumer for handling events to launch quick capture from launcher + * Input consumer for handling events to pass to an {@code OverscrollPlugin}. + * * @param Draggable activity subclass used by RecentsView */ -public class QuickCaptureInputConsumer - extends DelegateInputConsumer { +public class OverscrollInputConsumer extends DelegateInputConsumer { - private static final String TAG = "QuickCaptureInputConsumer"; - - private static final String QUICK_CAPTURE_PACKAGE = "com.google.auxe.compose"; - private static final String QUICK_CAPTURE_PACKAGE_DEV = "com.google.auxe.compose.debug"; - - private static final String EXTRA_DEVICE_STATE = "deviceState"; - private static final String DEVICE_STATE_LOCKED = "Locked"; - private static final String DEVICE_STATE_LAUNCHER = "Launcher"; - private static final String DEVICE_STATE_APP = "App"; - private static final String DEVICE_STATE_UNKNOWN = "Unknown"; + private static final String TAG = "OverscrollInputConsumer"; private static final int ANGLE_THRESHOLD = 35; // Degrees @@ -71,14 +60,16 @@ public class QuickCaptureInputConsumer private final Context mContext; private final GestureState mGestureState; + @Nullable private final OverscrollPlugin mPlugin; private RecentsView mRecentsView; - public QuickCaptureInputConsumer(Context context, GestureState gestureState, - InputConsumer delegate, InputMonitorCompat inputMonitor) { + public OverscrollInputConsumer(Context context, GestureState gestureState, + InputConsumer delegate, InputMonitorCompat inputMonitor, OverscrollPlugin plugin) { super(delegate, inputMonitor); mContext = context; mGestureState = gestureState; + mPlugin = plugin; float slop = ViewConfiguration.get(context).getScaledTouchSlop(); mSquaredSlop = slop * slop; @@ -89,7 +80,7 @@ public class QuickCaptureInputConsumer @Override public int getType() { - return TYPE_QUICK_CAPTURE | mDelegate.getType(); + return TYPE_OVERSCROLL | mDelegate.getType(); } private boolean onActivityInit(Boolean alreadyOnHome) { @@ -149,7 +140,7 @@ public class QuickCaptureInputConsumer mPassedSlop = true; mStartDragPos.set(mLastPos.x, mLastPos.y); - if (isValidQuickCaptureGesture()) { + if (isOverscrolled()) { setActive(ev); } else { mState = STATE_DELEGATE_ACTIVE; @@ -161,8 +152,8 @@ public class QuickCaptureInputConsumer } case ACTION_CANCEL: case ACTION_UP: - if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop) { - startQuickCapture(); + if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop && mPlugin != null) { + mPlugin.onOverscroll(getDeviceState()); } mPassedSlop = false; @@ -175,7 +166,7 @@ public class QuickCaptureInputConsumer } } - private boolean isValidQuickCaptureGesture() { + private boolean isOverscrolled() { // Make sure there isn't an app to quick switch to on our right boolean atRightMostApp = (mRecentsView == null || mRecentsView.getRunningTaskIndex() <= 0); @@ -187,37 +178,19 @@ public class QuickCaptureInputConsumer return atRightMostApp && angleInBounds; } - private void startQuickCapture() { - // Inspect our delegate's type to figure out where the user invoked Compose - String deviceState = DEVICE_STATE_UNKNOWN; + private String getDeviceState() { + String deviceState = OverscrollPlugin.DEVICE_STATE_UNKNOWN; int consumerType = mDelegate.getType(); if (((consumerType & InputConsumer.TYPE_OVERVIEW) > 0) || ((consumerType & InputConsumer.TYPE_OVERVIEW_WITHOUT_FOCUS)) > 0) { - deviceState = DEVICE_STATE_LAUNCHER; + deviceState = OverscrollPlugin.DEVICE_STATE_LAUNCHER; } else if ((consumerType & InputConsumer.TYPE_OTHER_ACTIVITY) > 0) { - deviceState = DEVICE_STATE_APP; + deviceState = OverscrollPlugin.DEVICE_STATE_APP; } else if (((consumerType & InputConsumer.TYPE_RESET_GESTURE) > 0) || ((consumerType & InputConsumer.TYPE_DEVICE_LOCKED) > 0)) { - deviceState = DEVICE_STATE_LOCKED; + deviceState = OverscrollPlugin.DEVICE_STATE_LOCKED; } - // Then launch the app - PackageManager pm = mContext.getPackageManager(); - - Intent qcIntent = pm.getLaunchIntentForPackage(QUICK_CAPTURE_PACKAGE); - - if (qcIntent == null) { - // If we couldn't find the regular app, try the dev version - qcIntent = pm.getLaunchIntentForPackage(QUICK_CAPTURE_PACKAGE_DEV); - } - - if (qcIntent != null) { - qcIntent.putExtra(EXTRA_DEVICE_STATE, deviceState); - - Bundle options = ActivityOptions.makeCustomAnimation(mContext, R.anim.slide_in_right, - 0).toBundle(); - - mContext.startActivity(qcIntent, options); - } + return deviceState; } } diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java index 918645d9aa..3e84e7d5ac 100644 --- a/quickstep/src/com/android/quickstep/InputConsumer.java +++ b/quickstep/src/com/android/quickstep/InputConsumer.java @@ -33,7 +33,7 @@ public interface InputConsumer { int TYPE_SCREEN_PINNED = 1 << 6; int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7; int TYPE_RESET_GESTURE = 1 << 8; - int TYPE_QUICK_CAPTURE = 1 << 9; + int TYPE_OVERSCROLL = 1 << 9; String[] NAMES = new String[] { "TYPE_NO_OP", // 0 @@ -45,7 +45,7 @@ public interface InputConsumer { "TYPE_SCREEN_PINNED", // 6 "TYPE_OVERVIEW_WITHOUT_FOCUS", // 7 "TYPE_RESET_GESTURE", // 8 - "TYPE_QUICK_CAPTURE", // 9 + "TYPE_OVERSCROLL", // 9 }; InputConsumer NO_OP = () -> TYPE_NO_OP; diff --git a/res/anim/slide_in_right.xml b/res/anim/slide_in_right.xml deleted file mode 100644 index 55d3e54025..0000000000 --- a/res/anim/slide_in_right.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java b/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java new file mode 100644 index 0000000000..60eb30418e --- /dev/null +++ b/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java @@ -0,0 +1,44 @@ +/* + * 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.systemui.plugins; + +import com.android.systemui.plugins.annotations.ProvidesInterface; + +/** + * Implement this interface to receive a callback when the user swipes right + * to left on the gesture area. It won't fire if the user has quick switched to a previous app + * (swiped right) and the current app isn't yet the active one (i.e., if swiping left would take + * the user to a more recent app). + */ +@ProvidesInterface(action = com.android.systemui.plugins.OverscrollPlugin.ACTION, + version = com.android.systemui.plugins.OverlayPlugin.VERSION) +public interface OverscrollPlugin extends Plugin { + + String ACTION = "com.android.systemui.action.PLUGIN_LAUNCHER_OVERSCROLL"; + int VERSION = 1; + + String DEVICE_STATE_LOCKED = "Locked"; + String DEVICE_STATE_LAUNCHER = "Launcher"; + String DEVICE_STATE_APP = "App"; + String DEVICE_STATE_UNKNOWN = "Unknown"; + + /** + * Called when the user completed a right to left swipe in the gesture area. + * + * @param deviceState One of the DEVICE_STATE_* constants. + */ + void onOverscroll(String deviceState); +}