Loading AndroidManifest-common.xml +1 −2 Original line number Diff line number Diff line Loading @@ -156,8 +156,7 @@ <provider android:name="com.android.launcher3.graphics.GridOptionsProvider" android:authorities="${packageName}.grid_control" android:exported="true" android:enabled="false" /> android:exported="true" /> <!-- The settings activity. To extend point settings_fragment_name to appropriate fragment class Loading quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +4 −2 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import com.android.launcher3.util.WindowBounds; import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.TransformParams; Loading @@ -61,7 +62,7 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend private static final String TAG = "BaseSwipeUpHandler"; protected final BaseActivityInterface<?, T> mActivityInterface; protected final InputConsumerController mInputConsumer; protected final InputConsumerProxy mInputConsumerProxy; protected final ActivityInitListener mActivityInitListener; Loading @@ -87,7 +88,8 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend super(context, deviceState, gestureState, new TransformParams()); mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); mInputConsumer = inputConsumer; mInputConsumerProxy = new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler); } /** Loading quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +3 −4 Original line number Diff line number Diff line Loading @@ -850,11 +850,9 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte } } if (endTarget.isLauncher && mRecentsAnimationController != null) { mRecentsAnimationController.enableInputProxy(mInputConsumer, this::createNewInputProxyHandler); if (endTarget.isLauncher) { mInputConsumerProxy.enable(); } if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); Loading Loading @@ -1181,6 +1179,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte } private void invalidateHandler() { mInputConsumerProxy.destroy(); endRunningWindowAnim(false /* cancel */); if (mGestureEndCallback != null) { Loading quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java 0 → 100644 +118 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.util; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; import android.util.Log; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import com.android.quickstep.InputConsumer; import com.android.systemui.shared.system.InputConsumerController; import java.util.function.Supplier; /** * Utility class which manages proxying input events from {@link InputConsumerController} * to an {@link InputConsumer} */ public class InputConsumerProxy { private static final String TAG = "InputConsumerProxy"; private final InputConsumerController mInputConsumerController; private final Supplier<InputConsumer> mConsumerSupplier; // The consumer is created lazily on demand. private InputConsumer mInputConsumer; private boolean mDestroyed = false; private boolean mTouchInProgress = false; private boolean mDestroyPending = false; public InputConsumerProxy(InputConsumerController inputConsumerController, Supplier<InputConsumer> consumerSupplier) { mInputConsumerController = inputConsumerController; mConsumerSupplier = consumerSupplier; } public void enable() { if (mDestroyed) { return; } mInputConsumerController.setInputListener(this::onInputConsumerEvent); } private boolean onInputConsumerEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); } else if (ev instanceof KeyEvent) { if (mInputConsumer == null) { mInputConsumer = mConsumerSupplier.get(); } mInputConsumer.onKeyEvent((KeyEvent) ev); return true; } return false; } private boolean onInputConsumerMotionEvent(MotionEvent ev) { int action = ev.getAction(); // Just to be safe, verify that ACTION_DOWN comes before any other action, // and ignore any ACTION_DOWN after the first one (though that should not happen). if (!mTouchInProgress && action != ACTION_DOWN) { Log.w(TAG, "Received non-down motion before down motion: " + action); return false; } if (mTouchInProgress && action == ACTION_DOWN) { Log.w(TAG, "Received down motion while touch was already in progress"); return false; } if (action == ACTION_DOWN) { mTouchInProgress = true; if (mInputConsumer == null) { mInputConsumer = mConsumerSupplier.get(); } } else if (action == ACTION_CANCEL || action == ACTION_UP) { // Finish any pending actions mTouchInProgress = false; if (mDestroyPending) { destroy(); } } if (mInputConsumer != null) { mInputConsumer.onMotionEvent(ev); } return true; } public void destroy() { if (mTouchInProgress) { mDestroyPending = true; return; } mDestroyPending = false; mDestroyed = true; mInputConsumerController.setInputListener(null); } } quickstep/src/com/android/quickstep/RecentsAnimationController.java +2 −101 Original line number Diff line number Diff line Loading @@ -15,49 +15,30 @@ */ package com.android.quickstep; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.os.SystemClock; import android.util.Log; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.android.launcher3.util.Preconditions; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.util.function.Consumer; import java.util.function.Supplier; /** * Wrapper around RecentsAnimationControllerCompat to help with some synchronization */ public class RecentsAnimationController { private static final String TAG = "RecentsAnimationController"; private final RecentsAnimationControllerCompat mController; private final Consumer<RecentsAnimationController> mOnFinishedListener; private final boolean mAllowMinimizeSplitScreen; private InputConsumerController mInputConsumerController; private Supplier<InputConsumer> mInputProxySupplier; private InputConsumer mInputConsumer; private boolean mUseLauncherSysBarFlags = false; private boolean mSplitScreenMinimized = false; private boolean mTouchInProgress; private boolean mDisableInputProxyPending; public RecentsAnimationController(RecentsAnimationControllerCompat controller, boolean allowMinimizeSplitScreen, Loading Loading @@ -136,12 +117,12 @@ public class RecentsAnimationController { @UiThread public void finishAnimationToHome() { finishAndDisableInputProxy(true /* toRecents */, null, false /* sendUserLeaveHint */); finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); } @UiThread public void finishAnimationToApp() { finishAndDisableInputProxy(false /* toRecents */, null, false /* sendUserLeaveHint */); finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); } /** See {@link #finish(boolean, Runnable, boolean)} */ Loading @@ -160,18 +141,6 @@ public class RecentsAnimationController { @UiThread public void finish(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { Preconditions.assertUIThread(); if (toRecents && mTouchInProgress) { // Finish the controller as requested, but don't disable input proxy yet. mDisableInputProxyPending = true; finishController(toRecents, onFinishComplete, sendUserLeaveHint); } else { finishAndDisableInputProxy(toRecents, onFinishComplete, sendUserLeaveHint); } } private void finishAndDisableInputProxy(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { disableInputProxy(); finishController(toRecents, onFinishComplete, sendUserLeaveHint); } Loading @@ -179,7 +148,6 @@ public class RecentsAnimationController { public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { mOnFinishedListener.accept(this); UI_HELPER_EXECUTOR.execute(() -> { mController.setInputConsumerEnabled(false); mController.finish(toRecents, sendUserLeaveHint); if (callback != null) { MAIN_EXECUTOR.execute(callback); Loading @@ -197,75 +165,8 @@ public class RecentsAnimationController { }); } public void enableInputProxy(InputConsumerController inputConsumerController, Supplier<InputConsumer> inputProxySupplier) { mInputProxySupplier = inputProxySupplier; mInputConsumerController = inputConsumerController; mInputConsumerController.setInputListener(this::onInputConsumerEvent); } /** @return wrapper controller. */ public RecentsAnimationControllerCompat getController() { return mController; } private void disableInputProxy() { if (mInputConsumer != null && mTouchInProgress) { long now = SystemClock.uptimeMillis(); MotionEvent dummyCancel = MotionEvent.obtain(now, now, ACTION_CANCEL, 0, 0, 0); mInputConsumer.onMotionEvent(dummyCancel); dummyCancel.recycle(); } if (mInputConsumerController != null) { mInputConsumerController.setInputListener(null); } mInputProxySupplier = null; } private boolean onInputConsumerEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); } else if (ev instanceof KeyEvent) { if (mInputConsumer == null) { mInputConsumer = mInputProxySupplier.get(); } mInputConsumer.onKeyEvent((KeyEvent) ev); return true; } return false; } private boolean onInputConsumerMotionEvent(MotionEvent ev) { int action = ev.getAction(); // Just to be safe, verify that ACTION_DOWN comes before any other action, // and ignore any ACTION_DOWN after the first one (though that should not happen). if (!mTouchInProgress && action != ACTION_DOWN) { Log.w(TAG, "Received non-down motion before down motion: " + action); return false; } if (mTouchInProgress && action == ACTION_DOWN) { Log.w(TAG, "Received down motion while touch was already in progress"); return false; } if (action == ACTION_DOWN) { mTouchInProgress = true; if (mInputConsumer == null) { mInputConsumer = mInputProxySupplier.get(); } } else if (action == ACTION_CANCEL || action == ACTION_UP) { // Finish any pending actions mTouchInProgress = false; if (mDisableInputProxyPending) { mDisableInputProxyPending = false; disableInputProxy(); } } if (mInputConsumer != null) { mInputConsumer.onMotionEvent(ev); } return true; } } Loading
AndroidManifest-common.xml +1 −2 Original line number Diff line number Diff line Loading @@ -156,8 +156,7 @@ <provider android:name="com.android.launcher3.graphics.GridOptionsProvider" android:authorities="${packageName}.grid_control" android:exported="true" android:enabled="false" /> android:exported="true" /> <!-- The settings activity. To extend point settings_fragment_name to appropriate fragment class Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +4 −2 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import com.android.launcher3.util.WindowBounds; import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.TransformParams; Loading @@ -61,7 +62,7 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend private static final String TAG = "BaseSwipeUpHandler"; protected final BaseActivityInterface<?, T> mActivityInterface; protected final InputConsumerController mInputConsumer; protected final InputConsumerProxy mInputConsumerProxy; protected final ActivityInitListener mActivityInitListener; Loading @@ -87,7 +88,8 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend super(context, deviceState, gestureState, new TransformParams()); mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); mInputConsumer = inputConsumer; mInputConsumerProxy = new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler); } /** Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +3 −4 Original line number Diff line number Diff line Loading @@ -850,11 +850,9 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte } } if (endTarget.isLauncher && mRecentsAnimationController != null) { mRecentsAnimationController.enableInputProxy(mInputConsumer, this::createNewInputProxyHandler); if (endTarget.isLauncher) { mInputConsumerProxy.enable(); } if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); Loading Loading @@ -1181,6 +1179,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte } private void invalidateHandler() { mInputConsumerProxy.destroy(); endRunningWindowAnim(false /* cancel */); if (mGestureEndCallback != null) { Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java 0 → 100644 +118 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.util; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; import android.util.Log; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import com.android.quickstep.InputConsumer; import com.android.systemui.shared.system.InputConsumerController; import java.util.function.Supplier; /** * Utility class which manages proxying input events from {@link InputConsumerController} * to an {@link InputConsumer} */ public class InputConsumerProxy { private static final String TAG = "InputConsumerProxy"; private final InputConsumerController mInputConsumerController; private final Supplier<InputConsumer> mConsumerSupplier; // The consumer is created lazily on demand. private InputConsumer mInputConsumer; private boolean mDestroyed = false; private boolean mTouchInProgress = false; private boolean mDestroyPending = false; public InputConsumerProxy(InputConsumerController inputConsumerController, Supplier<InputConsumer> consumerSupplier) { mInputConsumerController = inputConsumerController; mConsumerSupplier = consumerSupplier; } public void enable() { if (mDestroyed) { return; } mInputConsumerController.setInputListener(this::onInputConsumerEvent); } private boolean onInputConsumerEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); } else if (ev instanceof KeyEvent) { if (mInputConsumer == null) { mInputConsumer = mConsumerSupplier.get(); } mInputConsumer.onKeyEvent((KeyEvent) ev); return true; } return false; } private boolean onInputConsumerMotionEvent(MotionEvent ev) { int action = ev.getAction(); // Just to be safe, verify that ACTION_DOWN comes before any other action, // and ignore any ACTION_DOWN after the first one (though that should not happen). if (!mTouchInProgress && action != ACTION_DOWN) { Log.w(TAG, "Received non-down motion before down motion: " + action); return false; } if (mTouchInProgress && action == ACTION_DOWN) { Log.w(TAG, "Received down motion while touch was already in progress"); return false; } if (action == ACTION_DOWN) { mTouchInProgress = true; if (mInputConsumer == null) { mInputConsumer = mConsumerSupplier.get(); } } else if (action == ACTION_CANCEL || action == ACTION_UP) { // Finish any pending actions mTouchInProgress = false; if (mDestroyPending) { destroy(); } } if (mInputConsumer != null) { mInputConsumer.onMotionEvent(ev); } return true; } public void destroy() { if (mTouchInProgress) { mDestroyPending = true; return; } mDestroyPending = false; mDestroyed = true; mInputConsumerController.setInputListener(null); } }
quickstep/src/com/android/quickstep/RecentsAnimationController.java +2 −101 Original line number Diff line number Diff line Loading @@ -15,49 +15,30 @@ */ package com.android.quickstep; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.os.SystemClock; import android.util.Log; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.android.launcher3.util.Preconditions; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.util.function.Consumer; import java.util.function.Supplier; /** * Wrapper around RecentsAnimationControllerCompat to help with some synchronization */ public class RecentsAnimationController { private static final String TAG = "RecentsAnimationController"; private final RecentsAnimationControllerCompat mController; private final Consumer<RecentsAnimationController> mOnFinishedListener; private final boolean mAllowMinimizeSplitScreen; private InputConsumerController mInputConsumerController; private Supplier<InputConsumer> mInputProxySupplier; private InputConsumer mInputConsumer; private boolean mUseLauncherSysBarFlags = false; private boolean mSplitScreenMinimized = false; private boolean mTouchInProgress; private boolean mDisableInputProxyPending; public RecentsAnimationController(RecentsAnimationControllerCompat controller, boolean allowMinimizeSplitScreen, Loading Loading @@ -136,12 +117,12 @@ public class RecentsAnimationController { @UiThread public void finishAnimationToHome() { finishAndDisableInputProxy(true /* toRecents */, null, false /* sendUserLeaveHint */); finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); } @UiThread public void finishAnimationToApp() { finishAndDisableInputProxy(false /* toRecents */, null, false /* sendUserLeaveHint */); finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); } /** See {@link #finish(boolean, Runnable, boolean)} */ Loading @@ -160,18 +141,6 @@ public class RecentsAnimationController { @UiThread public void finish(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { Preconditions.assertUIThread(); if (toRecents && mTouchInProgress) { // Finish the controller as requested, but don't disable input proxy yet. mDisableInputProxyPending = true; finishController(toRecents, onFinishComplete, sendUserLeaveHint); } else { finishAndDisableInputProxy(toRecents, onFinishComplete, sendUserLeaveHint); } } private void finishAndDisableInputProxy(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { disableInputProxy(); finishController(toRecents, onFinishComplete, sendUserLeaveHint); } Loading @@ -179,7 +148,6 @@ public class RecentsAnimationController { public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { mOnFinishedListener.accept(this); UI_HELPER_EXECUTOR.execute(() -> { mController.setInputConsumerEnabled(false); mController.finish(toRecents, sendUserLeaveHint); if (callback != null) { MAIN_EXECUTOR.execute(callback); Loading @@ -197,75 +165,8 @@ public class RecentsAnimationController { }); } public void enableInputProxy(InputConsumerController inputConsumerController, Supplier<InputConsumer> inputProxySupplier) { mInputProxySupplier = inputProxySupplier; mInputConsumerController = inputConsumerController; mInputConsumerController.setInputListener(this::onInputConsumerEvent); } /** @return wrapper controller. */ public RecentsAnimationControllerCompat getController() { return mController; } private void disableInputProxy() { if (mInputConsumer != null && mTouchInProgress) { long now = SystemClock.uptimeMillis(); MotionEvent dummyCancel = MotionEvent.obtain(now, now, ACTION_CANCEL, 0, 0, 0); mInputConsumer.onMotionEvent(dummyCancel); dummyCancel.recycle(); } if (mInputConsumerController != null) { mInputConsumerController.setInputListener(null); } mInputProxySupplier = null; } private boolean onInputConsumerEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); } else if (ev instanceof KeyEvent) { if (mInputConsumer == null) { mInputConsumer = mInputProxySupplier.get(); } mInputConsumer.onKeyEvent((KeyEvent) ev); return true; } return false; } private boolean onInputConsumerMotionEvent(MotionEvent ev) { int action = ev.getAction(); // Just to be safe, verify that ACTION_DOWN comes before any other action, // and ignore any ACTION_DOWN after the first one (though that should not happen). if (!mTouchInProgress && action != ACTION_DOWN) { Log.w(TAG, "Received non-down motion before down motion: " + action); return false; } if (mTouchInProgress && action == ACTION_DOWN) { Log.w(TAG, "Received down motion while touch was already in progress"); return false; } if (action == ACTION_DOWN) { mTouchInProgress = true; if (mInputConsumer == null) { mInputConsumer = mInputProxySupplier.get(); } } else if (action == ACTION_CANCEL || action == ACTION_UP) { // Finish any pending actions mTouchInProgress = false; if (mDisableInputProxyPending) { mDisableInputProxyPending = false; disableInputProxy(); } } if (mInputConsumer != null) { mInputConsumer.onMotionEvent(ev); } return true; } }