From e30660b155799cc34e57be6054b6968f57a7d0b2 Mon Sep 17 00:00:00 2001 From: John Andrew Camu Date: Sun, 2 Jun 2024 16:26:42 +0800 Subject: [PATCH] Fixed crashes with gesture (#4417) * Add support A14 QPR2 --- .../ten/ActivityManagerCompatVQ.java | 3 +++ .../twelve/QuickstepCompatFactoryVS.java | 8 +++++-- .../thirteen/ActivityOptionsCompatVT.java | 2 -- .../com/android/quickstep/SystemUiProxy.java | 22 +++++++++++++++++++ .../quickstep/util/FadeOutRemoteTransition.kt | 2 ++ .../util/SplitSelectStateController.java | 2 ++ .../rotation/RotationButtonController.java | 21 ++++++++++++++++-- .../system/InputConsumerController.java | 20 +++++++++++++++-- .../RecentsAnimationControllerCompat.java | 22 ++++++++++++++++--- .../system/RemoteAnimationRunnerCompat.java | 2 ++ 10 files changed, 93 insertions(+), 11 deletions(-) diff --git a/compatLib/compatLibVQ/src/main/java/app/lawnchair/compatlib/ten/ActivityManagerCompatVQ.java b/compatLib/compatLibVQ/src/main/java/app/lawnchair/compatlib/ten/ActivityManagerCompatVQ.java index f6cd27dfc1..7f799a27b4 100644 --- a/compatLib/compatLibVQ/src/main/java/app/lawnchair/compatlib/ten/ActivityManagerCompatVQ.java +++ b/compatLib/compatLibVQ/src/main/java/app/lawnchair/compatlib/ten/ActivityManagerCompatVQ.java @@ -72,6 +72,9 @@ public class ActivityManagerCompatVQ implements ActivityManagerCompat { public void onAnimationCanceled(boolean deferredWithScreenshot) { runnerCompat.onAnimationCanceled(deferredWithScreenshot); } + + // Samsung OneUi + public void reportAllDrawn() {} }; } try { diff --git a/compatLib/compatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java b/compatLib/compatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java index 8e5dddacdc..c8a56869e1 100644 --- a/compatLib/compatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java +++ b/compatLib/compatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java @@ -30,7 +30,11 @@ public class QuickstepCompatFactoryVS extends QuickstepCompatFactoryVR { @NonNull @Override public RemoteTransitionCompat getRemoteTransitionCompat() { - return this::createRemoteTransition; + try { + return this::createRemoteTransition; + } catch (Throwable t) { + return super.getRemoteTransitionCompat(); + } } // TODO remove this as it causing glitches on first launch opening/closing app @@ -40,7 +44,7 @@ public class QuickstepCompatFactoryVS extends QuickstepCompatFactoryVR { Class remoteTransitionClass = Class.forName("android.window.RemoteTransition"); Constructor constructor = remoteTransitionClass.getConstructor( - IRemoteTransition.class, IApplicationThread.class, String.class); + IRemoteTransition.class, IApplicationThread.class); return (RemoteTransition) constructor.newInstance(remoteTransition, appThread); } catch (ClassNotFoundException | IllegalAccessException diff --git a/compatLib/compatLibVT/src/main/java/app/lawnchair/compatlib/thirteen/ActivityOptionsCompatVT.java b/compatLib/compatLibVT/src/main/java/app/lawnchair/compatlib/thirteen/ActivityOptionsCompatVT.java index 5a0edc3d6b..b1fd91c088 100644 --- a/compatLib/compatLibVT/src/main/java/app/lawnchair/compatlib/thirteen/ActivityOptionsCompatVT.java +++ b/compatLib/compatLibVT/src/main/java/app/lawnchair/compatlib/thirteen/ActivityOptionsCompatVT.java @@ -3,7 +3,6 @@ package app.lawnchair.compatlib.thirteen; import android.app.ActivityOptions; import android.content.Context; import android.os.Handler; -import android.util.Log; import android.view.RemoteAnimationAdapter; import android.window.RemoteTransition; import androidx.annotation.NonNull; @@ -20,7 +19,6 @@ public class ActivityOptionsCompatVT extends ActivityOptionsCompatVS { @Nullable RemoteAnimationAdapter remoteAnimationAdapter, @Nullable Object remoteTransition, @Nullable String debugName) { - Log.e(TAG, "makeRemoteAnimation: " + debugName); return ActivityOptions.makeRemoteAnimation( remoteAnimationAdapter, (RemoteTransition) remoteTransition); } diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 88cd3caa64..6cee8df0d1 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -52,6 +52,7 @@ import android.window.IOnBackInvokedCallback; import android.window.RemoteTransition; import android.window.TaskSnapshot; import android.window.TransitionFilter; +import android.window.TransitionInfo; import androidx.annotation.MainThread; import androidx.annotation.Nullable; @@ -1471,6 +1472,27 @@ public class SystemUiProxy implements ISystemUiProxy { wallpapers, homeContentInsets, minimizedHomeBounds); } + // Android 14 QPR2 + public void onAnimationStart(IRecentsAnimationController controller, + RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, + Rect homeContentInsets, Rect minimizedHomeBounds, Bundle bundle) { + listener.onAnimationStart(new RecentsAnimationControllerCompat(controller), apps, + wallpapers, homeContentInsets, minimizedHomeBounds); + } + + // NothingOS with Android 14 2.5.5 + public void onAnimationStartWithSurfaceTransaction( + IRecentsAnimationController controller, + TransitionInfo transitionInfo, + SurfaceControl.Transaction transaction, + RemoteAnimationTarget[] apps, + RemoteAnimationTarget[] wallpapers, + Rect homeContentInsets, + Rect minimizedHomeBounds) { + listener.onAnimationStart(new RecentsAnimationControllerCompat(controller), apps, + wallpapers, homeContentInsets, minimizedHomeBounds); + } + @Override public void onAnimationCanceled(int[] taskIds, TaskSnapshot[] taskSnapshots) { listener.onAnimationCanceled( diff --git a/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt b/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt index 59ff81da4e..4a0c5d8afa 100644 --- a/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt +++ b/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt @@ -83,4 +83,6 @@ class FadeOutRemoteTransition : IRemoteTransition.Stub() { Executors.MAIN_EXECUTOR.execute { anim.start() } } + + fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {} } diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index 454d2cbb19..f97535db7e 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -604,6 +604,8 @@ public class SplitSelectStateController { public void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, IBinder mergeTarget, IRemoteTransitionFinishedCallback finishedCallback) { } + + public void onTransitionConsumed(IBinder transition, boolean aborted) {} } /** diff --git a/systemUIShared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/systemUIShared/src/com/android/systemui/shared/rotation/RotationButtonController.java index b48a0a80fc..16ac066d37 100644 --- a/systemUIShared/src/com/android/systemui/shared/rotation/RotationButtonController.java +++ b/systemUIShared/src/com/android/systemui/shared/rotation/RotationButtonController.java @@ -69,6 +69,8 @@ import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Optional; import java.util.concurrent.Executor; import java.util.function.Supplier; @@ -288,8 +290,23 @@ public class RotationButtonController { // Ignore if we can't read the setting for the current user return; } - RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isLocked, - /* rotation= */ rotationSuggestion); + hookSetRotationLockAtAngle(mContext, isLocked, rotationSuggestion); + } + + /** + * RotationPolicy @setRotationLockAtAngle Reflection + */ + private void hookSetRotationLockAtAngle(Context mContext, boolean isLocked, int rotationSuggestion) { + try { + Class rotationPolicyClass = Class.forName("com.android.internal.view.RotationPolicy"); + Method setRotationLockAtAngleMethod = rotationPolicyClass.getDeclaredMethod("setRotationLockAtAngle", Context.class, boolean.class, int.class, String.class); + setRotationLockAtAngleMethod.setAccessible(true); + setRotationLockAtAngleMethod.invoke(null, mContext, isLocked, rotationSuggestion, "Lawnchair"); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | + InvocationTargetException e) { + RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isLocked, + /* rotation= */ rotationSuggestion); + } } /** diff --git a/systemUIShared/src/com/android/systemui/shared/system/InputConsumerController.java b/systemUIShared/src/com/android/systemui/shared/system/InputConsumerController.java index ba0a6d1497..9ce10fd762 100644 --- a/systemUIShared/src/com/android/systemui/shared/system/InputConsumerController.java +++ b/systemUIShared/src/com/android/systemui/shared/system/InputConsumerController.java @@ -32,6 +32,8 @@ import android.view.InputEvent; import android.view.WindowManagerGlobal; import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; /** * Manages the input consumer that allows the SystemUI to directly receive input. @@ -139,7 +141,7 @@ public class InputConsumerController { if (mInputEventReceiver == null) { final InputChannel inputChannel = new InputChannel(); try { - mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY); + hookDestroyInputConsumer(mWindowManager); mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel); } catch (RemoteException e) { Log.e(TAG, "Failed to create input consumer", e); @@ -152,13 +154,27 @@ public class InputConsumerController { } } + /** + * IWindowManager @destroyInputConsumer reflection + */ + private void hookDestroyInputConsumer(IWindowManager mWindowManager) throws RemoteException { + try { + Class iWindowManagerClass = Class.forName("android.view.IWindowManager"); + Method destroyInputConsumerMethod = iWindowManagerClass.getMethod("destroyInputConsumer", IBinder.class, int.class); + destroyInputConsumerMethod.invoke(mWindowManager, mToken, DEFAULT_DISPLAY); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | + InvocationTargetException e) { + mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY); + } + } + /** * Unregisters the input consumer. */ public void unregisterInputConsumer() { if (mInputEventReceiver != null) { try { - mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY); + hookDestroyInputConsumer(mWindowManager); } catch (RemoteException e) { Log.e(TAG, "Failed to destroy input consumer", e); } diff --git a/systemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/systemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java index 338f9c544b..ea579a98db 100644 --- a/systemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java +++ b/systemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java @@ -25,9 +25,11 @@ import android.window.TaskSnapshot; import com.android.systemui.shared.recents.model.ThumbnailData; -import app.lawnchair.compat.LawnchairQuickstepCompat; -import app.lawnchair.compatlib.eleven.ActivityManagerCompatVR; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import app.lawnchair.compat.LawnchairQuickstepCompat; +import com.android.internal.os.IResultReceiver; public class RecentsAnimationControllerCompat { private static final String TAG = RecentsAnimationControllerCompat.class.getSimpleName(); @@ -99,12 +101,26 @@ public class RecentsAnimationControllerCompat { */ public void finish(boolean toHome, boolean sendUserLeaveHint) { try { - mAnimationController.finish(toHome, sendUserLeaveHint); + hookIrecentsController(toHome, sendUserLeaveHint); } catch (RemoteException e) { Log.e(TAG, "Failed to finish recents animation", e); } } + /** + * IRecentsAnimationController @finish reflection + */ + private void hookIrecentsController(boolean toHome, boolean sendUserLeaveHint) throws RemoteException { + try { + Class iRecentsAnimationControllerClass = Class.forName("android.view.IRecentsAnimationController"); + Method finishMethod = iRecentsAnimationControllerClass.getMethod("finish", boolean.class, boolean.class, IResultReceiver.class); + finishMethod.invoke(mAnimationController, toHome, sendUserLeaveHint, null); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | + InvocationTargetException e) { + mAnimationController.finish(toHome, sendUserLeaveHint); + } + } + public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) { try { mAnimationController.setDeferCancelUntilNextTransition(defer, screenshot); diff --git a/systemUIShared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java b/systemUIShared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java index e56dc02e98..1ecc9a2732 100644 --- a/systemUIShared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java +++ b/systemUIShared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java @@ -93,6 +93,8 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner return new IRemoteTransition.Stub() { final ArrayMap mFinishRunnables = new ArrayMap<>(); + public void onTransitionConsumed(IBinder transition, boolean aborted) {} + @Override public void startAnimation(IBinder token, TransitionInfo info, SurfaceControl.Transaction t,