diff options
12 files changed, 250 insertions, 156 deletions
diff --git a/core/java/android/view/accessibility/IRemoteMagnificationAnimationCallback.aidl b/core/java/android/view/accessibility/IRemoteMagnificationAnimationCallback.aidl new file mode 100644 index 000000000000..946ea16575bd --- /dev/null +++ b/core/java/android/view/accessibility/IRemoteMagnificationAnimationCallback.aidl @@ -0,0 +1,33 @@ +/* + * 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 android.view.accessibility; + +/** + * A callback for magnification animation result. + * @hide + */ + + oneway interface IRemoteMagnificationAnimationCallback { + + /** + * Called when the animation is finished or interrupted during animating. + * + * @param success {@code true} if animating successfully with given spec or the spec did not + * change. Otherwise {@code false} + */ + void onResult(boolean success); +} diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl index ae853e952d25..ddf68fcb1311 100644 --- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl +++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl @@ -18,8 +18,8 @@ package android.view.accessibility; import android.graphics.PointF; import android.graphics.Rect; -import android.os.RemoteCallback; import android.view.accessibility.IWindowMagnificationConnectionCallback; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; /** * Interface for interaction between {@link AccessibilityManagerService} @@ -38,10 +38,10 @@ oneway interface IWindowMagnificationConnection { * or {@link Float#NaN} to leave unchanged. * @param centerY the screen-relative Y coordinate around which to center, * or {@link Float#NaN} to leave unchanged. - * @param endCallback The callback called when the animation is completed. + * @param callback The callback called when the animation is completed or interrupted. */ void enableWindowMagnification(int displayId, float scale, float centerX, float centerY, - in RemoteCallback endCallback); + in IRemoteMagnificationAnimationCallback callback); /** * Sets the scale of the window magnifier on specified display. @@ -55,9 +55,10 @@ oneway interface IWindowMagnificationConnection { * Disables window magnification on specified display with animation. * * @param displayId The logical display id. - * @param endCallback The callback called when the animation is completed. + * @param callback The callback called when the animation is completed or interrupted. */ - void disableWindowMagnification(int displayId, in RemoteCallback endCallback); + void disableWindowMagnification(int displayId, + in IRemoteMagnificationAnimationCallback callback); /** * Moves the window magnifier on the specified display. It has no effect while animating. diff --git a/core/java/android/view/accessibility/MagnificationAnimationCallback.java b/core/java/android/view/accessibility/MagnificationAnimationCallback.java index 491f7fb32a8c..bc9fb0a3e5e0 100644 --- a/core/java/android/view/accessibility/MagnificationAnimationCallback.java +++ b/core/java/android/view/accessibility/MagnificationAnimationCallback.java @@ -28,4 +28,4 @@ public interface MagnificationAnimationCallback { * change. Otherwise {@code false} */ void onResult(boolean success); -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index e10d2be4cb5e..911bf9ef757b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -24,11 +24,11 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Handler; -import android.os.RemoteCallback; import android.os.RemoteException; import android.util.Log; import android.view.SurfaceControl; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; @@ -101,10 +101,10 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall @MainThread void enableWindowMagnification(int displayId, float scale, float centerX, float centerY, - @Nullable RemoteCallback endCallback) { + @Nullable IRemoteMagnificationAnimationCallback callback) { //TODO: b/144080869 support multi-display. mWindowMagnificationAnimationController.enableWindowMagnification(scale, centerX, centerY, - endCallback != null ? () -> endCallback.sendResult(null) : null); + callback); } @MainThread @@ -120,10 +120,10 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall } @MainThread - void disableWindowMagnification(int displayId, @Nullable RemoteCallback endCallback) { + void disableWindowMagnification(int displayId, + @Nullable IRemoteMagnificationAnimationCallback callback) { //TODO: b/144080869 support multi-display. - mWindowMagnificationAnimationController.deleteWindowMagnification( - endCallback != null ? () -> endCallback.sendResult(null) : null); + mWindowMagnificationAnimationController.deleteWindowMagnification(callback); } @Override @@ -182,10 +182,10 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall @Override public void enableWindowMagnification(int displayId, float scale, float centerX, - float centerY, RemoteCallback remoteCallback) { + float centerY, IRemoteMagnificationAnimationCallback callback) { mHandler.post( () -> mWindowMagnification.enableWindowMagnification(displayId, scale, centerX, - centerY, remoteCallback)); + centerY, callback)); } @Override @@ -194,9 +194,10 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall } @Override - public void disableWindowMagnification(int displayId, RemoteCallback remoteCallback) { + public void disableWindowMagnification(int displayId, + IRemoteMagnificationAnimationCallback callback) { mHandler.post(() -> mWindowMagnification.disableWindowMagnification(displayId, - remoteCallback)); + callback)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java index 2f2e3eaddd3b..24d83884f093 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java @@ -22,7 +22,9 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.content.Context; import android.content.res.Resources; +import android.os.RemoteException; import android.util.Log; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.animation.AccelerateInterpolator; import com.android.internal.annotations.VisibleForTesting; @@ -38,7 +40,7 @@ import java.lang.annotation.RetentionPolicy; class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener { - private static final String TAG = "WindowMagnificationBridge"; + private static final String TAG = "WindowMagnificationAnimationController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @Retention(RetentionPolicy.SOURCE) @@ -61,7 +63,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp private final Context mContext; // Called when the animation is ended successfully without cancelling or mStartSpec and // mEndSpec are equal. - private Runnable mAnimationEndCallback; + private IRemoteMagnificationAnimationCallback mAnimationCallback; // The flag to ignore the animation end callback. private boolean mEndAnimationCanceled = false; @MagnificationState @@ -93,14 +95,16 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp * or {@link Float#NaN} to leave unchanged. * @param centerY The screen-relative Y coordinate around which to center, * or {@link Float#NaN} to leave unchanged. - * @param animationEndCallback Called when the transition is complete or the given arguments - * are as same as current values. + * @param animationCallback Called when the transition is complete, the given arguments + * are as same as current values, or the transition is interrupted + * due to the new transition request. * * @see #onAnimationUpdate(ValueAnimator) */ void enableWindowMagnification(float scale, float centerX, float centerY, - @Nullable Runnable animationEndCallback) { - mAnimationEndCallback = animationEndCallback; + @Nullable IRemoteMagnificationAnimationCallback animationCallback) { + sendAnimationCallback(false); + mAnimationCallback = animationCallback; setupEnableAnimationSpecs(scale, centerX, centerY); if (mEndSpec.equals(mStartSpec)) { if (mState == STATE_DISABLED) { @@ -108,7 +112,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp } else if (mState == STATE_ENABLING || mState == STATE_DISABLING) { mValueAnimator.cancel(); } - sendCallbackIfNeeded(); + sendAnimationCallback(true); setState(STATE_ENABLED); } else { if (mState == STATE_DISABLING) { @@ -160,14 +164,17 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp * Wraps {@link WindowMagnificationController#deleteWindowMagnification()}} with transition * animation. If the window magnification is enabling, it runs the animation in reverse. * - * @param animationEndCallback Called when the transition is complete or the window - * magnification is disabled already. + * @param animationCallback Called when the transition is complete, the given arguments + * are as same as current values, or the transition is interrupted + * due to the new transition request. */ - void deleteWindowMagnification(@Nullable Runnable animationEndCallback) { - mAnimationEndCallback = animationEndCallback; + void deleteWindowMagnification( + @Nullable IRemoteMagnificationAnimationCallback animationCallback) { + sendAnimationCallback(false); + mAnimationCallback = animationCallback; if (mState == STATE_DISABLED || mState == STATE_DISABLING) { if (mState == STATE_DISABLED) { - sendCallbackIfNeeded(); + sendAnimationCallback(true); } return; } @@ -220,7 +227,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp } else { setState(STATE_ENABLED); } - sendCallbackIfNeeded(); + sendAnimationCallback(true); } @Override @@ -236,10 +243,17 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp public void onAnimationRepeat(Animator animation) { } - private void sendCallbackIfNeeded() { - if (mAnimationEndCallback != null) { - mAnimationEndCallback.run(); - mAnimationEndCallback = null; + private void sendAnimationCallback(boolean success) { + if (mAnimationCallback != null) { + try { + mAnimationCallback.onResult(success); + if (DEBUG) { + Log.d(TAG, "sendAnimationCallback success = " + success); + } + } catch (RemoteException e) { + Log.w(TAG, "sendAnimationCallback failed : " + e); + } + mAnimationCallback = null; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java index 9079338cd502..1e969c226ff1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java @@ -23,13 +23,13 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; import android.content.Context; -import android.os.RemoteCallback; import android.os.RemoteException; import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Display; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; @@ -41,7 +41,6 @@ import com.android.systemui.statusbar.CommandQueue; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -66,8 +65,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Mock private ModeSwitchesController mModeSwitchesController; @Mock - private RemoteCallback mRemoteCallback; - private ArgumentCaptor<Runnable> mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class); + private IRemoteMagnificationAnimationCallback mAnimationCallback; private IWindowMagnificationConnection mIWindowMagnificationConnection; private WindowMagnification mWindowMagnification; @@ -92,22 +90,21 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Test public void enableWindowMagnification_passThrough() throws RemoteException { mIWindowMagnificationConnection.enableWindowMagnification(TEST_DISPLAY, 3.0f, Float.NaN, - Float.NaN, mRemoteCallback); + Float.NaN, mAnimationCallback); waitForIdleSync(); verify(mWindowMagnificationAnimationController).enableWindowMagnification(eq(3.0f), - eq(Float.NaN), eq(Float.NaN), mRunnableCaptor.capture()); - verifyRunnableWrapsRemoteCallback(mRunnableCaptor.getValue()); + eq(Float.NaN), eq(Float.NaN), eq(mAnimationCallback)); } @Test public void disableWindowMagnification_deleteWindowMagnification() throws RemoteException { - mIWindowMagnificationConnection.disableWindowMagnification(TEST_DISPLAY, mRemoteCallback); + mIWindowMagnificationConnection.disableWindowMagnification(TEST_DISPLAY, + mAnimationCallback); waitForIdleSync(); verify(mWindowMagnificationAnimationController).deleteWindowMagnification( - mRunnableCaptor.capture()); - verifyRunnableWrapsRemoteCallback(mRunnableCaptor.getValue()); + mAnimationCallback); } @Test @@ -143,10 +140,5 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { verify(mModeSwitchesController).removeButton(TEST_DISPLAY); } - - private void verifyRunnableWrapsRemoteCallback(Runnable runnable) { - runnable.run(); - verify(mRemoteCallback).sendResult(null); - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java index d74c62b90fda..33b1d94df80e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -18,6 +18,7 @@ package com.android.systemui.accessibility; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.never; @@ -28,9 +29,11 @@ import android.annotation.Nullable; import android.app.Instrumentation; import android.content.Context; import android.os.Handler; +import android.os.RemoteException; import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.view.SurfaceControl; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.animation.AccelerateInterpolator; import androidx.test.InstrumentationRegistry; @@ -75,9 +78,9 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { @Mock WindowMagnifierCallback mWindowMagnifierCallback; @Mock - Runnable mAnimationEndCallback; + IRemoteMagnificationAnimationCallback mAnimationCallback; @Mock - Runnable mAnimationEndCallback2; + IRemoteMagnificationAnimationCallback mAnimationCallback2; private SpyWindowMagnificationController mController; private WindowMagnificationController mSpyController; private WindowMagnificationAnimationController mWindowMagnificationAnimationController; @@ -105,8 +108,9 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { } @Test - public void enableWindowMagnification_disabled_expectedValuesAndInvokeCallback() { - enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationEndCallback); + public void enableWindowMagnification_disabled_expectedValuesAndInvokeCallback() + throws RemoteException { + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback); verify(mSpyController, atLeast(2)).enableWindowMagnification( mScaleCaptor.capture(), @@ -115,28 +119,30 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { verifyStartValue(mCenterXCaptor, DEFAULT_CENTER_X); verifyStartValue(mCenterYCaptor, DEFAULT_CENTER_Y); verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y); - verify(mAnimationEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test - public void enableWindowMagnificationWithScaleOne_disabled_NoAnimationAndInvokeCallback() { + public void enableWindowMagnificationWithScaleOne_disabled_NoAnimationAndInvokeCallback() + throws RemoteException { mInstrumentation.runOnMainSync( () -> { mWindowMagnificationAnimationController.enableWindowMagnification(1, - DEFAULT_CENTER_X, DEFAULT_CENTER_Y, mAnimationEndCallback); + DEFAULT_CENTER_X, DEFAULT_CENTER_Y, mAnimationCallback); }); SystemClock.sleep(mWaitingAnimationPeriod); verify(mSpyController).enableWindowMagnification(1, DEFAULT_CENTER_X, DEFAULT_CENTER_Y); - verify(mAnimationEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test - public void enableWindowMagnification_enabling_expectedValuesAndInvokeCallback() { + public void enableWindowMagnification_enabling_expectedValuesAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); final float targetScale = DEFAULT_SCALE + 1.0f; final float targetCenterX = DEFAULT_CENTER_X + 100; final float targetCenterY = DEFAULT_CENTER_Y + 100; @@ -144,7 +150,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { mInstrumentation.runOnMainSync(() -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.enableWindowMagnification(targetScale, - targetCenterX, targetCenterY, mAnimationEndCallback2); + targetCenterX, targetCenterY, mAnimationCallback2); mCurrentScale.set(mController.getScale()); mCurrentCenterX.set(mController.getCenterX()); mCurrentCenterY.set(mController.getCenterY()); @@ -158,33 +164,35 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { verifyStartValue(mCenterXCaptor, mCurrentCenterX.get()); verifyStartValue(mCenterYCaptor, mCurrentCenterY.get()); verifyFinalSpec(targetScale, targetCenterX, targetCenterY); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback).onResult(false); + verify(mAnimationCallback2).onResult(true); } @Test - public void enableWindowMagnificationWithSameSpec_enabling_NoAnimationAndInvokeCallback() { + public void enableWindowMagnificationWithSameSpec_enabling_NoAnimationAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); mInstrumentation.runOnMainSync(() -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN, - Float.NaN, Float.NaN, mAnimationEndCallback2); + Float.NaN, Float.NaN, mAnimationCallback2); }); SystemClock.sleep(mWaitingAnimationPeriod); verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(), anyFloat()); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback).onResult(false); + verify(mAnimationCallback2).onResult(true); } @Test - public void enableWindowMagnification_disabling_expectedValuesAndInvokeCallback() { + public void enableWindowMagnification_disabling_expectedValuesAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null); deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); final float targetScale = DEFAULT_SCALE + 1.0f; final float targetCenterX = DEFAULT_CENTER_X + 100; final float targetCenterY = DEFAULT_CENTER_Y + 100; @@ -193,13 +201,14 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { () -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.enableWindowMagnification(targetScale, - targetCenterX, targetCenterY, mAnimationEndCallback2); + targetCenterX, targetCenterY, mAnimationCallback2); mCurrentScale.set(mController.getScale()); mCurrentCenterX.set(mController.getCenterX()); mCurrentCenterY.set(mController.getCenterY()); }); // Current spec shouldn't match given spec. - verify(mAnimationEndCallback2, never()).run(); + verify(mAnimationCallback2, never()).onResult(anyBoolean()); + verify(mAnimationCallback).onResult(false); SystemClock.sleep(mWaitingAnimationPeriod); verify(mSpyController, atLeast(2)).enableWindowMagnification( @@ -213,34 +222,35 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { assertTrue(mCenterYCaptor.getAllValues().get(0) > mCurrentCenterY.get()); assertEquals(targetCenterY, mCenterYCaptor.getValue(), 0f); verifyFinalSpec(targetScale, targetCenterX, targetCenterY); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback2).onResult(true); } @Test - public void enableWindowMagnificationWithSameSpec_disabling_NoAnimationAndInvokeCallback() { + public void enableWindowMagnificationWithSameSpec_disabling_NoAnimationAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null); deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); mInstrumentation.runOnMainSync(() -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.enableWindowMagnification(Float.NaN, - Float.NaN, Float.NaN, mAnimationEndCallback2); + Float.NaN, Float.NaN, mAnimationCallback2); }); SystemClock.sleep(mWaitingAnimationPeriod); verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(), anyFloat()); verify(mSpyController, never()).deleteWindowMagnification(); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback).onResult(false); + verify(mAnimationCallback2).onResult(true); } @Test - public void enableWindowMagnification_enabled_expectedValuesAndInvokeCallback() { + public void enableWindowMagnification_enabled_expectedValuesAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); final float targetScale = DEFAULT_SCALE + 1.0f; final float targetCenterX = DEFAULT_CENTER_X + 100; final float targetCenterY = DEFAULT_CENTER_Y + 100; @@ -248,7 +258,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { mInstrumentation.runOnMainSync(() -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.enableWindowMagnification(targetScale, - targetCenterX, targetCenterY, mAnimationEndCallback2); + targetCenterX, targetCenterY, mAnimationCallback2); mCurrentScale.set(mController.getScale()); mCurrentCenterX.set(mController.getCenterX()); mCurrentCenterY.set(mController.getCenterY()); @@ -262,19 +272,20 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { verifyStartValue(mCenterXCaptor, mCurrentCenterX.get()); verifyStartValue(mCenterYCaptor, mCurrentCenterY.get()); verifyFinalSpec(targetScale, targetCenterX, targetCenterY); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback).onResult(false); + verify(mAnimationCallback2).onResult(true); } @Test - public void enableWindowMagnificationWithSameScale_enabled_doNothingButInvokeCallback() { + public void enableWindowMagnificationWithSameScale_enabled_doNothingButInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null); - enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationEndCallback); + enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback); verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(), anyFloat()); - verify(mAnimationEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test @@ -289,10 +300,11 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { } @Test - public void deleteWindowMagnification_enabled_expectedValuesAndInvokeCallback() { + public void deleteWindowMagnification_enabled_expectedValuesAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null); - deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationEndCallback); + deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback); verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture()); @@ -301,27 +313,29 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { verifyStartValue(mCenterXCaptor, Float.NaN); verifyStartValue(mCenterYCaptor, Float.NaN); verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN); - verify(mAnimationEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test - public void deleteWindowMagnification_disabled_doNothingAndInvokeCallback() { - deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationEndCallback); + public void deleteWindowMagnification_disabled_doNothingAndInvokeCallback() + throws RemoteException { + deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback); Mockito.verifyNoMoreInteractions(mSpyController); - verify(mAnimationEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test - public void deleteWindowMagnification_enabling_expectedValuesAndInvokeCallback() { + public void deleteWindowMagnification_enabling_expectedValuesAndInvokeCallback() + throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); mInstrumentation.runOnMainSync( () -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.deleteWindowMagnification( - mAnimationEndCallback2); + mAnimationCallback2); mCurrentScale.set(mController.getScale()); mCurrentCenterX.set(mController.getCenterX()); mCurrentCenterY.set(mController.getCenterY()); @@ -339,25 +353,25 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { verifyStartValue(mCenterXCaptor, Float.NaN); verifyStartValue(mCenterYCaptor, Float.NaN); verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback).onResult(false); + verify(mAnimationCallback2).onResult(true); } @Test - public void deleteWindowMagnification_disabling_checkStartAndValues() { + public void deleteWindowMagnification_disabling_checkStartAndValues() throws RemoteException { enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null); deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod, - mAnimationEndCallback); + mAnimationCallback); - deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationEndCallback2); + deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback2); verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(), mCenterXCaptor.capture(), mCenterYCaptor.capture()); verify(mSpyController).deleteWindowMagnification(); assertEquals(1.0f, mScaleCaptor.getValue(), 0f); verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN); - verify(mAnimationEndCallback, never()).run(); - verify(mAnimationEndCallback2).run(); + verify(mAnimationCallback).onResult(false); + verify(mAnimationCallback2).onResult(true); } @Test @@ -386,22 +400,22 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { } private void enableWindowMagnificationAndWaitAnimating(long duration, - @Nullable Runnable endCallback) { + @Nullable IRemoteMagnificationAnimationCallback callback) { mInstrumentation.runOnMainSync( () -> { Mockito.reset(mSpyController); mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE, - DEFAULT_CENTER_X, DEFAULT_CENTER_Y, endCallback); + DEFAULT_CENTER_X, DEFAULT_CENTER_Y, callback); }); SystemClock.sleep(duration); } private void deleteWindowMagnificationAndWaitAnimating(long duration, - @Nullable Runnable endCallback) { + @Nullable IRemoteMagnificationAnimationCallback callback) { mInstrumentation.runOnMainSync( () -> { resetMockObjects(); - mWindowMagnificationAnimationController.deleteWindowMagnification(endCallback); + mWindowMagnificationAnimationController.deleteWindowMagnification(callback); }); SystemClock.sleep(duration); } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java index a401bcd3eabd..993027d1ca3c 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java @@ -20,11 +20,12 @@ import static android.os.IBinder.DeathRecipient; import android.annotation.NonNull; import android.annotation.Nullable; -import android.os.RemoteCallback; import android.os.RemoteException; import android.util.Slog; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; +import android.view.accessibility.MagnificationAnimationCallback; /** * A wrapper of {@link IWindowMagnificationConnection}. @@ -50,9 +51,10 @@ class WindowMagnificationConnectionWrapper { } boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY, - @Nullable RemoteCallback endCallback) { + @Nullable MagnificationAnimationCallback callback) { try { - mConnection.enableWindowMagnification(displayId, scale, centerX, centerY, endCallback); + mConnection.enableWindowMagnification(displayId, scale, centerX, centerY, + transformToRemoteCallback(callback)); } catch (RemoteException e) { if (DBG) { Slog.e(TAG, "Error calling enableWindowMagnification()", e); @@ -74,9 +76,10 @@ class WindowMagnificationConnectionWrapper { return true; } - boolean disableWindowMagnification(int displayId, @Nullable RemoteCallback endCallback) { + boolean disableWindowMagnification(int displayId, + @Nullable MagnificationAnimationCallback callback) { try { - mConnection.disableWindowMagnification(displayId, endCallback); + mConnection.disableWindowMagnification(displayId, transformToRemoteCallback(callback)); } catch (RemoteException e) { if (DBG) { Slog.e(TAG, "Error calling disableWindowMagnification()", e); @@ -134,4 +137,27 @@ class WindowMagnificationConnectionWrapper { return true; } + private static @Nullable + IRemoteMagnificationAnimationCallback transformToRemoteCallback( + MagnificationAnimationCallback callback) { + if (callback == null) { + return null; + } + return new RemoteAnimationCallback(callback); + } + + private static class RemoteAnimationCallback extends + IRemoteMagnificationAnimationCallback.Stub { + + private final MagnificationAnimationCallback mCallback; + + RemoteAnimationCallback(@NonNull MagnificationAnimationCallback callback) { + mCallback = callback; + } + + @Override + public void onResult(boolean success) throws RemoteException { + mCallback.onResult(success); + } + } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java index d3d56d7f857d..d78d99e0a74b 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java @@ -24,7 +24,6 @@ import android.content.IntentFilter; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; -import android.os.RemoteCallback; import android.os.RemoteException; import android.provider.Settings; import android.util.MathUtils; @@ -33,6 +32,7 @@ import android.util.SparseArray; import android.view.MotionEvent; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; +import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -234,17 +234,17 @@ public class WindowMagnificationManager implements * or {@link Float#NaN} to leave unchanged. * @param centerY The screen-relative Y coordinate around which to center, * or {@link Float#NaN} to leave unchanged. - * @param endCallback Called when the animation is ended without any interruption or the - * window magnifier is disabled already. + * @param animationCallback Called when the animation result is valid. */ void enableWindowMagnification(int displayId, float scale, float centerX, float centerY, - @Nullable Runnable endCallback) { + @Nullable MagnificationAnimationCallback animationCallback) { synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); if (magnifier == null) { magnifier = createWindowMagnifier(displayId); } - magnifier.enableWindowMagnificationInternal(scale, centerX, centerY, endCallback); + magnifier.enableWindowMagnificationInternal(scale, centerX, centerY, + animationCallback); } } @@ -263,16 +263,16 @@ public class WindowMagnificationManager implements * * @param displayId The logical display id. * @param clear {@true} Clears the state of window magnification. - * @param endCallback Called when the animation is ended without any interruption or the - * window magnifier is disabled already. + * @param animationCallback Called when the animation result is valid. */ - void disableWindowMagnification(int displayId, boolean clear, Runnable endCallback) { + void disableWindowMagnification(int displayId, boolean clear, + MagnificationAnimationCallback animationCallback) { synchronized (mLock) { WindowMagnifier magnifier = mWindowMagnifiers.get(displayId); if (magnifier == null) { return; } - magnifier.disableWindowMagnificationInternal(endCallback); + magnifier.disableWindowMagnificationInternal(animationCallback); if (clear) { mWindowMagnifiers.delete(displayId); } @@ -481,22 +481,23 @@ public class WindowMagnificationManager implements @GuardedBy("mLock") void enableWindowMagnificationInternal(float scale, float centerX, float centerY, - @Nullable Runnable endCallback) { + @Nullable MagnificationAnimationCallback animationCallback) { if (mEnabled) { return; } final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE); if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale, - centerX, centerY, endCallback)) { + centerX, centerY, animationCallback)) { mScale = normScale; mEnabled = true; } } @GuardedBy("mLock") - void disableWindowMagnificationInternal(@Nullable Runnable endCallback) { + void disableWindowMagnificationInternal( + @Nullable MagnificationAnimationCallback animationResultCallback) { if (mEnabled && mWindowMagnificationManager.disableWindowMagnificationInternal( - mDisplayId, endCallback)) { + mDisplayId, animationResultCallback)) { mEnabled = false; } } @@ -558,20 +559,19 @@ public class WindowMagnificationManager implements } private boolean enableWindowMagnificationInternal(int displayId, float scale, float centerX, - float centerY, Runnable endCallback) { + float centerY, MagnificationAnimationCallback animationCallback) { return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification( - displayId, scale, centerX, centerY, - endCallback != null ? new RemoteCallback(bundle -> endCallback.run()) : null); + displayId, scale, centerX, centerY, animationCallback); } private boolean setScaleInternal(int displayId, float scale) { return mConnectionWrapper != null && mConnectionWrapper.setScale(displayId, scale); } - private boolean disableWindowMagnificationInternal(int displayId, Runnable endCallback) { + private boolean disableWindowMagnificationInternal(int displayId, + MagnificationAnimationCallback animationCallback) { return mConnectionWrapper != null && mConnectionWrapper.disableWindowMagnification( - displayId, - endCallback != null ? new RemoteCallback(bundle -> endCallback.run()) : null); + displayId, animationCallback); } private boolean moveWindowMagnifierInternal(int displayId, float offsetX, float offsetY) { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java index f896d75ecb3b..10322e7ceff0 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java @@ -28,9 +28,9 @@ import static org.mockito.Mockito.when; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; -import android.os.RemoteCallback; import android.os.RemoteException; import android.view.Display; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; @@ -38,7 +38,7 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback; * Mocks the basic logic of window magnification in System UI. We assume the screen size is * unlimited, so source bounds is always on the center of the mirror window bounds. */ -class MockWindowMagnificationConnection { +class MockWindowMagnificationConnection { public static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; private final IWindowMagnificationConnection mConnection; @@ -72,27 +72,30 @@ class MockWindowMagnificationConnection { throw new IllegalArgumentException("only support default display :" + displayId); } computeMirrorWindowFrame(invocation.getArgument(2), invocation.getArgument(3)); - final RemoteCallback callback = invocation.getArgument(4); + final IRemoteMagnificationAnimationCallback callback = invocation.getArgument(4); if (callback != null) { - callback.sendResult(null); + callback.onResult(true); + } + if (mIMirrorWindowCallback != null) { + mIMirrorWindowCallback.onWindowMagnifierBoundsChanged(TEST_DISPLAY, + mMirrorWindowFrame); } - mIMirrorWindowCallback.onWindowMagnifierBoundsChanged(TEST_DISPLAY, - mMirrorWindowFrame); return null; - }).when(mConnection).enableWindowMagnification(anyInt(), - anyFloat(), anyFloat(), anyFloat(), nullable(RemoteCallback.class)); + }).when(mConnection).enableWindowMagnification(anyInt(), anyFloat(), anyFloat(), anyFloat(), + nullable(IRemoteMagnificationAnimationCallback.class)); doAnswer((invocation) -> { final int displayId = invocation.getArgument(0); if (displayId != TEST_DISPLAY) { throw new IllegalArgumentException("only support default display :" + displayId); } - final RemoteCallback callback = invocation.getArgument(1); + final IRemoteMagnificationAnimationCallback callback = invocation.getArgument(1); if (callback != null) { - callback.sendResult(null); + callback.onResult(true); } return null; - }).when(mConnection).disableWindowMagnification(anyInt(), nullable(RemoteCallback.class)); + }).when(mConnection).disableWindowMagnification(anyInt(), + nullable(IRemoteMagnificationAnimationCallback.class)); } private void computeMirrorWindowFrame(float centerX, float centerY) { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java index 9ef65d9cce09..c88bc3b2e15b 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java @@ -17,14 +17,17 @@ package com.android.server.accessibility.magnification; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; -import android.os.RemoteCallback; import android.os.RemoteException; import android.provider.Settings; import android.view.Display; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.view.accessibility.IWindowMagnificationConnection; import android.view.accessibility.IWindowMagnificationConnectionCallback; +import android.view.accessibility.MagnificationAnimationCallback; import org.junit.Before; import org.junit.Test; @@ -40,26 +43,29 @@ public class WindowMagnificationConnectionWrapperTest { private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; - @Mock private IWindowMagnificationConnection mConnection; @Mock private IWindowMagnificationConnectionCallback mCallback; @Mock - private RemoteCallback.OnResultListener mOnResultListener; - private RemoteCallback mRemoteCallback; + private MagnificationAnimationCallback mAnimationCallback; + + private MockWindowMagnificationConnection mMockWindowMagnificationConnection; private WindowMagnificationConnectionWrapper mConnectionWrapper; @Before - public void setUp() { + public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); + mMockWindowMagnificationConnection = new MockWindowMagnificationConnection(); + mConnection = mMockWindowMagnificationConnection.getConnection(); mConnectionWrapper = new WindowMagnificationConnectionWrapper(mConnection); - mRemoteCallback = new RemoteCallback(mOnResultListener); } @Test public void enableWindowMagnification() throws RemoteException { - mConnectionWrapper.enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f, mRemoteCallback); - verify(mConnection).enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f, mRemoteCallback); + mConnectionWrapper.enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f, + mAnimationCallback); + + verify(mAnimationCallback).onResult(true); } @Test @@ -70,8 +76,11 @@ public class WindowMagnificationConnectionWrapperTest { @Test public void disableWindowMagnification() throws RemoteException { - mConnectionWrapper.disableWindowMagnification(TEST_DISPLAY, mRemoteCallback); - verify(mConnection).disableWindowMagnification(TEST_DISPLAY, mRemoteCallback); + mConnectionWrapper.disableWindowMagnification(TEST_DISPLAY, mAnimationCallback); + + verify(mConnection).disableWindowMagnification(eq(TEST_DISPLAY), + any(IRemoteMagnificationAnimationCallback.class)); + verify(mAnimationCallback).onResult(true); } @Test @@ -99,5 +108,4 @@ public class WindowMagnificationConnectionWrapperTest { mConnectionWrapper.setConnectionCallback(mCallback); verify(mConnection).setConnectionCallback(mCallback); } - } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java index dcb1262ad2de..9366e9535ab9 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java @@ -48,6 +48,7 @@ import android.view.Display; import android.view.InputDevice; import android.view.MotionEvent; import android.view.accessibility.IWindowMagnificationConnectionCallback; +import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; @@ -73,7 +74,7 @@ public class WindowMagnificationManagerTest { @Mock private StatusBarManagerInternal mMockStatusBarManagerInternal; @Mock - private Runnable mEndCallback; + private MagnificationAnimationCallback mAnimationCallback; private MockContentResolver mResolver; private WindowMagnificationManager mWindowMagnificationManager; @@ -177,9 +178,9 @@ public class WindowMagnificationManagerTest { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f, - mEndCallback); + mAnimationCallback); - verify(mEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test @@ -198,9 +199,10 @@ public class WindowMagnificationManagerTest { mWindowMagnificationManager.setConnection(mMockConnection.getConnection()); mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN); - mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false, mEndCallback); + mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false, + mAnimationCallback); - verify(mEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test |