diff options
9 files changed, 72 insertions, 118 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index cb82278ca577..54ee37519546 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -7504,8 +7504,6 @@ public final class ViewRootImpl implements ViewParent, final KeyEvent event = (KeyEvent)q.mEvent; if (mView.dispatchKeyEventPreIme(event)) { return FINISH_HANDLED; - } else if (q.forPreImeOnly()) { - return FINISH_NOT_HANDLED; } return FORWARD; } @@ -10002,7 +10000,6 @@ public final class ViewRootImpl implements ViewParent, public static final int FLAG_RESYNTHESIZED = 1 << 4; public static final int FLAG_UNHANDLED = 1 << 5; public static final int FLAG_MODIFIED_FOR_COMPATIBILITY = 1 << 6; - public static final int FLAG_PRE_IME_ONLY = 1 << 7; public QueuedInputEvent mNext; @@ -10010,13 +10007,6 @@ public final class ViewRootImpl implements ViewParent, public InputEventReceiver mReceiver; public int mFlags; - public boolean forPreImeOnly() { - if ((mFlags & FLAG_PRE_IME_ONLY) != 0) { - return true; - } - return false; - } - public boolean shouldSkipIme() { if ((mFlags & FLAG_DELIVER_POST_IME) != 0) { return true; @@ -10043,7 +10033,6 @@ public final class ViewRootImpl implements ViewParent, hasPrevious = flagToString("FINISHED_HANDLED", FLAG_FINISHED_HANDLED, hasPrevious, sb); hasPrevious = flagToString("RESYNTHESIZED", FLAG_RESYNTHESIZED, hasPrevious, sb); hasPrevious = flagToString("UNHANDLED", FLAG_UNHANDLED, hasPrevious, sb); - hasPrevious = flagToString("FLAG_PRE_IME_ONLY", FLAG_PRE_IME_ONLY, hasPrevious, sb); if (!hasPrevious) { sb.append("0"); } @@ -10100,7 +10089,7 @@ public final class ViewRootImpl implements ViewParent, } @UnsupportedAppUsage - QueuedInputEvent enqueueInputEvent(InputEvent event, + void enqueueInputEvent(InputEvent event, InputEventReceiver receiver, int flags, boolean processImmediately) { QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags); @@ -10139,7 +10128,6 @@ public final class ViewRootImpl implements ViewParent, } else { scheduleProcessInputEvents(); } - return q; } private void scheduleProcessInputEvents() { @@ -12461,45 +12449,29 @@ public final class ViewRootImpl implements ViewParent, + "IWindow:%s Session:%s", mOnBackInvokedDispatcher, mBasePackageName, mWindow, mWindowSession)); } - mOnBackInvokedDispatcher.attachToWindow(mWindowSession, mWindow, this, + mOnBackInvokedDispatcher.attachToWindow(mWindowSession, mWindow, mImeBackAnimationController); } - /** - * Sends {@link KeyEvent#ACTION_DOWN ACTION_DOWN} and {@link KeyEvent#ACTION_UP ACTION_UP} - * back key events - * - * @param preImeOnly whether the back events should be sent to the pre-ime stage only - * @return whether the event was handled (i.e. onKeyPreIme consumed it if preImeOnly=true) - */ - public boolean injectBackKeyEvents(boolean preImeOnly) { - boolean consumed; - try { - processingBackKey(true); - sendBackKeyEvent(KeyEvent.ACTION_DOWN, preImeOnly); - consumed = sendBackKeyEvent(KeyEvent.ACTION_UP, preImeOnly); - } finally { - processingBackKey(false); - } - return consumed; - } - - private boolean sendBackKeyEvent(int action, boolean preImeOnly) { + private void sendBackKeyEvent(int action) { long when = SystemClock.uptimeMillis(); final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_KEYBOARD); - int flags = preImeOnly ? QueuedInputEvent.FLAG_PRE_IME_ONLY : 0; - QueuedInputEvent q = enqueueInputEvent(ev, null /* receiver */, flags, - true /* processImmediately */); - return (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0; + enqueueInputEvent(ev, null /* receiver */, 0 /* flags */, true /* processImmediately */); } private void registerCompatOnBackInvokedCallback() { mCompatOnBackInvokedCallback = () -> { - injectBackKeyEvents(/* preImeOnly */ false); + try { + processingBackKey(true); + sendBackKeyEvent(KeyEvent.ACTION_DOWN); + sendBackKeyEvent(KeyEvent.ACTION_UP); + } finally { + processingBackKey(false); + } }; if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) { Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher"); diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 4c993c2544ce..b7f6f363dd04 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -37,7 +37,6 @@ import android.view.IWindow; import android.view.IWindowSession; import android.view.ImeBackAnimationController; import android.view.MotionEvent; -import android.view.ViewRootImpl; import androidx.annotation.VisibleForTesting; @@ -50,7 +49,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Objects; import java.util.TreeMap; -import java.util.function.BooleanSupplier; import java.util.function.Supplier; /** @@ -70,7 +68,6 @@ import java.util.function.Supplier; public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { private IWindowSession mWindowSession; private IWindow mWindow; - private ViewRootImpl mViewRoot; @VisibleForTesting public final BackTouchTracker mTouchTracker = new BackTouchTracker(); @VisibleForTesting @@ -137,12 +134,10 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { * is attached a window. */ public void attachToWindow(@NonNull IWindowSession windowSession, @NonNull IWindow window, - @Nullable ViewRootImpl viewRoot, @Nullable ImeBackAnimationController imeBackAnimationController) { synchronized (mLock) { mWindowSession = windowSession; mWindow = window; - mViewRoot = viewRoot; mImeBackAnimationController = imeBackAnimationController; if (!mAllCallbacks.isEmpty()) { setTopOnBackInvokedCallback(getTopCallback()); @@ -156,7 +151,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { clear(); mWindow = null; mWindowSession = null; - mViewRoot = null; mImeBackAnimationController = null; } } @@ -182,6 +176,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { return; } if (callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) { + // Fall back to compat back key injection if legacy back behaviour should be used. + if (!isOnBackInvokedCallbackEnabled()) return; if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback && mImeBackAnimationController != null) { // register ImeBackAnimationController instead to play predictive back animation @@ -304,14 +300,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } - private boolean callOnKeyPreIme() { - if (mViewRoot != null && !isOnBackInvokedCallbackEnabled(mViewRoot.mContext)) { - return mViewRoot.injectBackKeyEvents(/*preImeOnly*/ true); - } else { - return false; - } - } - private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) { if (mWindowSession == null || mWindow == null) { return; @@ -320,8 +308,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { OnBackInvokedCallbackInfo callbackInfo = null; if (callback != null) { int priority = mAllCallbacks.get(callback); - final IOnBackInvokedCallback iCallback = new OnBackInvokedCallbackWrapper(callback, - mTouchTracker, mProgressAnimator, mHandler, this::callOnKeyPreIme); + final IOnBackInvokedCallback iCallback = new OnBackInvokedCallbackWrapper( + callback, mTouchTracker, mProgressAnimator, mHandler); callbackInfo = new OnBackInvokedCallbackInfo( iCallback, priority, @@ -411,20 +399,16 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { private final BackTouchTracker mTouchTracker; @NonNull private final Handler mHandler; - @NonNull - private final BooleanSupplier mOnKeyPreIme; OnBackInvokedCallbackWrapper( @NonNull OnBackInvokedCallback callback, @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, - @NonNull Handler handler, - @NonNull BooleanSupplier onKeyPreIme) { + @NonNull Handler handler) { mCallback = new WeakReference<>(callback); mTouchTracker = touchTracker; mProgressAnimator = progressAnimator; mHandler = handler; - mOnKeyPreIme = onKeyPreIme; } @Override @@ -467,7 +451,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { public void onBackInvoked() throws RemoteException { mHandler.post(() -> { mTouchTracker.reset(); - if (consumedByOnKeyPreIme()) return; boolean isInProgress = mProgressAnimator.isBackAnimationInProgress(); final OnBackInvokedCallback callback = mCallback.get(); if (callback == null) { @@ -489,30 +472,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { }); } - private boolean consumedByOnKeyPreIme() { - final OnBackInvokedCallback callback = mCallback.get(); - if (callback instanceof ImeBackAnimationController - || callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) { - // call onKeyPreIme API if the current callback is an IME callback and the app has - // not set enableOnBackInvokedCallback="false" - try { - boolean consumed = mOnKeyPreIme.getAsBoolean(); - if (consumed) { - // back event intercepted by app in onKeyPreIme -> cancel the IME animation. - final OnBackAnimationCallback animationCallback = - getBackAnimationCallback(); - if (animationCallback != null) { - mProgressAnimator.onBackCancelled(animationCallback::onBackCancelled); - } - return true; - } - } catch (Exception e) { - Log.d(TAG, "Failed to call onKeyPreIme", e); - } - } - return false; - } - @Override public void setTriggerBack(boolean triggerBack) throws RemoteException { mTouchTracker.setTriggerBack(triggerBack); diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 98d6ec6897a6..920981e2b8fe 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -923,7 +923,7 @@ public class ResolverActivity extends Activity implements mSystemWindowInsets = insets.getSystemWindowInsets(); mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top, - mSystemWindowInsets.right, mSystemWindowInsets.bottom); + mSystemWindowInsets.right, 0); resetButtonBar(); @@ -952,7 +952,7 @@ public class ResolverActivity extends Activity implements if (mSystemWindowInsets != null) { mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top, - mSystemWindowInsets.right, mSystemWindowInsets.bottom); + mSystemWindowInsets.right, 0); } } diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java index d4482f243939..b0190a5c8218 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -112,7 +112,7 @@ public class WindowOnBackInvokedDispatcherTest { doReturn(mApplicationInfo).when(mContext).getApplicationInfo(); mDispatcher = new WindowOnBackInvokedDispatcher(mContext, Looper.getMainLooper()); - mDispatcher.attachToWindow(mWindowSession, mWindow, null, mImeBackAnimationController); + mDispatcher.attachToWindow(mWindowSession, mWindow, mImeBackAnimationController); } private void waitForIdle() { @@ -455,26 +455,25 @@ public class WindowOnBackInvokedDispatcherTest { @Test public void registerImeCallbacks_onBackInvokedCallbackEnabled() throws RemoteException { - verifyImeCallackRegistrations(); - } - - @Test - public void registerImeCallbacks_onBackInvokedCallbackDisabled() throws RemoteException { - doReturn(false).when(mApplicationInfo).isOnBackInvokedCallbackEnabled(); - verifyImeCallackRegistrations(); - } - - private void verifyImeCallackRegistrations() throws RemoteException { - // verify default callback is replaced with ImeBackAnimationController - mDispatcher.registerOnBackInvokedCallbackUnchecked(mDefaultImeCallback, PRIORITY_DEFAULT); + mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback); assertCallbacksSize(/* default */ 1, /* overlay */ 0); assertSetCallbackInfo(); assertTopCallback(mImeBackAnimationController); - // verify regular ime callback is successfully registered - mDispatcher.registerOnBackInvokedCallbackUnchecked(mImeCallback, PRIORITY_DEFAULT); + mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback); assertCallbacksSize(/* default */ 2, /* overlay */ 0); assertSetCallbackInfo(); assertTopCallback(mImeCallback); } + + @Test + public void registerImeCallbacks_legacyBack() throws RemoteException { + doReturn(false).when(mApplicationInfo).isOnBackInvokedCallbackEnabled(); + + mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback); + assertNoSetCallbackInfo(); + + mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback); + assertNoSetCallbackInfo(); + } } diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java index 959300629cd7..f85d786f89c5 100644 --- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java @@ -101,8 +101,10 @@ class UiAutomationManager { SystemActionPerformer systemActionPerformer, AccessibilityWindowManager awm, int flags) { accessibilityServiceInfo.setComponentName(COMPONENT_NAME); - Slogf.i(LOG_TAG, "Registering UiTestAutomationService (id=%s) when called by user %d", - accessibilityServiceInfo.getId(), Binder.getCallingUserHandle().getIdentifier()); + Slogf.i(LOG_TAG, "Registering UiTestAutomationService (id=%s, flags=0x%x) when" + + " called by user %d", + accessibilityServiceInfo.getId(), flags, + Binder.getCallingUserHandle().getIdentifier()); if (mUiAutomationService != null) { throw new IllegalStateException( "UiAutomationService " + mUiAutomationService.mServiceInterface diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index 6710d02bee90..988e8fea70b9 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -56,10 +56,17 @@ final class VibratorController { private volatile boolean mIsUnderExternalControl; private volatile float mCurrentAmplitude; - /** Listener for vibration completion callbacks from native. */ + /** + * Listener for vibration completion callbacks from native. + * + * <p>Only the latest active native call to {@link VibratorController#on} will ever trigger this + * completion callback, to avoid race conditions during a vibration playback. If a new call to + * {@link #on} or {@link #off} happens before a previous callback was triggered then the + * previous callback will be disabled, even if the new command fails. + */ public interface OnVibrationCompleteListener { - /** Callback triggered when vibration is complete. */ + /** Callback triggered when an active vibration command is complete. */ void onComplete(int vibratorId, long vibrationId); } @@ -235,7 +242,7 @@ final class VibratorController { } /** - * Turn on the vibrator for {@code milliseconds} time, using {@code vibrationId} or completion + * Turn on the vibrator for {@code milliseconds} time, using {@code vibrationId} for completion * callback to {@link OnVibrationCompleteListener}. * * <p>This will affect the state of {@link #isVibrating()}. @@ -255,7 +262,7 @@ final class VibratorController { } /** - * Plays predefined vibration effect, using {@code vibrationId} or completion callback to + * Plays predefined vibration effect, using {@code vibrationId} for completion callback to * {@link OnVibrationCompleteListener}. * * <p>This will affect the state of {@link #isVibrating()}. @@ -276,8 +283,8 @@ final class VibratorController { } /** - * Plays a composition of vibration primitives, using {@code vibrationId} or completion callback - * to {@link OnVibrationCompleteListener}. + * Plays a composition of vibration primitives, using {@code vibrationId} for completion + * callback to {@link OnVibrationCompleteListener}. * * <p>This will affect the state of {@link #isVibrating()}. * @@ -299,7 +306,7 @@ final class VibratorController { } /** - * Plays a composition of pwle primitives, using {@code vibrationId} or completion callback + * Plays a composition of pwle primitives, using {@code vibrationId} for completion callback * to {@link OnVibrationCompleteListener}. * * <p>This will affect the state of {@link #isVibrating()}. @@ -321,7 +328,11 @@ final class VibratorController { } } - /** Turns off the vibrator. This will affect the state of {@link #isVibrating()}. */ + /** + * Turns off the vibrator and disables completion callback to any pending vibration. + * + * <p>This will affect the state of {@link #isVibrating()}. + */ public void off() { synchronized (mLock) { mNativeWrapper.off(); diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index f47a59d6cec9..4be21d872383 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -131,17 +131,28 @@ public: } std::function<void()> createCallback(jlong vibrationId) { - return [vibrationId, this]() { + auto callbackId = ++mCallbackId; + return [vibrationId, callbackId, this]() { + auto currentCallbackId = mCallbackId.load(); + if (currentCallbackId != callbackId) { + // This callback is from an older HAL call that is no longer relevant to the service + return; + } auto jniEnv = GetOrAttachJNIEnvironment(sJvm); jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId, vibrationId); }; } + void disableOldCallbacks() { + mCallbackId++; + } + private: const std::shared_ptr<vibrator::HalController> mHal; const int32_t mVibratorId; const jobject mCallbackListener; + std::atomic<int64_t> mCallbackId; }; static aidl::BrakingPwle brakingPwle(aidl::Braking braking, int32_t duration) { @@ -236,6 +247,7 @@ static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong ptr) { } auto offFn = [](vibrator::HalWrapper* hal) { return hal->off(); }; wrapper->halCall<void>(offFn, "off"); + wrapper->disableOldCallbacks(); } static void vibratorSetAmplitude(JNIEnv* env, jclass /* clazz */, jlong ptr, jfloat amplitude) { diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java index 19ce217e581c..9dac23f075e6 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java @@ -1681,7 +1681,7 @@ public class VibrationThreadTest { .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK) .compose(); VibrationEffect effect4 = VibrationEffect.createOneShot(8000, 100); - VibrationEffect effect5 = VibrationEffect.createOneShot(20, 222); + VibrationEffect effect5 = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); long vibrationId1 = startThreadAndDispatcher(effect1); waitForCompletion(); @@ -1745,13 +1745,12 @@ public class VibrationThreadTest { verifyCallbacksTriggered(vibrationId4, Vibration.Status.CANCELLED_BY_SCREEN_OFF); assertTrue("Tested duration=" + duration4, duration4 < 2000); - // Effect5: normal oneshot. Don't worry about amplitude, as effect4 may or may not have - // started. + // Effect5: played normally after effect4, which may or may not have played. verify(mControllerCallbacks).onComplete(eq(VIBRATOR_ID), eq(vibrationId5)); verifyCallbacksTriggered(vibrationId5, Vibration.Status.FINISHED); - assertEquals(Arrays.asList(expectedOneShot(20)), + assertEquals(Arrays.asList(expectedPrebaked(VibrationEffect.EFFECT_CLICK)), fakeVibrator.getEffectSegments(vibrationId5)); } diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index c67d1ec63827..a39a1a8637df 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -550,7 +550,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { }).when(appWindow.mSession).setOnBackInvokedCallbackInfo(eq(appWindow.mClient), any()); addToWindowMap(appWindow, true); - dispatcher.attachToWindow(appWindow.mSession, appWindow.mClient, null, null); + dispatcher.attachToWindow(appWindow.mSession, appWindow.mClient, null); OnBackInvokedCallback appCallback = createBackCallback(appLatch); |