summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/accessibility/MagnificationAnimationCallback.java31
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java85
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java43
3 files changed, 97 insertions, 62 deletions
diff --git a/core/java/android/view/accessibility/MagnificationAnimationCallback.java b/core/java/android/view/accessibility/MagnificationAnimationCallback.java
new file mode 100644
index 000000000000..491f7fb32a8c
--- /dev/null
+++ b/core/java/android/view/accessibility/MagnificationAnimationCallback.java
@@ -0,0 +1,31 @@
+/*
+ * 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 android.view.accessibility;
+
+/**
+ * A callback for magnification animation result.
+ * @hide
+ */
+public interface MagnificationAnimationCallback {
+ /**
+ * 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/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index b6f2a47dd5e2..c583dcc2b1be 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -37,6 +37,7 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.MagnificationSpec;
import android.view.View;
+import android.view.accessibility.MagnificationAnimationCallback;
import android.view.animation.DecelerateInterpolator;
import com.android.internal.R;
@@ -63,7 +64,7 @@ public class FullScreenMagnificationController {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "FullScreenMagnificationController";
- private static final Runnable STUB_RUNNABLE = () -> {
+ private static final MagnificationAnimationCallback STUB_ANIMATION_CALLBACK = success -> {
};
public static final float MIN_SCALE = 1.0f;
public static final float MAX_SCALE = 8.0f;
@@ -304,18 +305,19 @@ public class FullScreenMagnificationController {
}
}
- void sendSpecToAnimation(MagnificationSpec spec, Runnable endCallback) {
+ void sendSpecToAnimation(MagnificationSpec spec,
+ MagnificationAnimationCallback animationCallback) {
if (DEBUG) {
Slog.i(LOG_TAG,
- "sendSpecToAnimation(spec = " + spec + ", endCallback = " + endCallback
- + ")");
+ "sendSpecToAnimation(spec = " + spec + ", animationCallback = "
+ + animationCallback + ")");
}
if (Thread.currentThread().getId() == mMainThreadId) {
- mSpecAnimationBridge.updateSentSpecMainThread(spec, endCallback);
+ mSpecAnimationBridge.updateSentSpecMainThread(spec, animationCallback);
} else {
final Message m = PooledLambda.obtainMessage(
SpecAnimationBridge::updateSentSpecMainThread,
- mSpecAnimationBridge, spec, endCallback);
+ mSpecAnimationBridge, spec, animationCallback);
mControllerCtx.getHandler().sendMessage(m);
}
}
@@ -415,11 +417,11 @@ public class FullScreenMagnificationController {
@GuardedBy("mLock")
boolean reset(boolean animate) {
- return reset(transformToStubRunnable(animate));
+ return reset(transformToStubCallback(animate));
}
@GuardedBy("mLock")
- boolean reset(Runnable endCallback) {
+ boolean reset(MagnificationAnimationCallback animationCallback) {
if (!mRegistered) {
return false;
}
@@ -430,7 +432,7 @@ public class FullScreenMagnificationController {
onMagnificationChangedLocked();
}
mIdOfLastServiceToMagnify = INVALID_ID;
- sendSpecToAnimation(spec, endCallback);
+ sendSpecToAnimation(spec, animationCallback);
return changed;
}
@@ -458,24 +460,23 @@ public class FullScreenMagnificationController {
final float centerX = normPivotX + offsetX;
final float centerY = normPivotY + offsetY;
mIdOfLastServiceToMagnify = id;
- return setScaleAndCenter(scale, centerX, centerY, transformToStubRunnable(animate), id);
+ return setScaleAndCenter(scale, centerX, centerY, transformToStubCallback(animate), id);
}
@GuardedBy("mLock")
boolean setScaleAndCenter(float scale, float centerX, float centerY,
- Runnable endCallback, int id) {
+ MagnificationAnimationCallback animationCallback, int id) {
if (!mRegistered) {
return false;
}
if (DEBUG) {
Slog.i(LOG_TAG,
"setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
- + ", centerY = " + centerY + ", endCallback = " + endCallback
- + ", id = " + id
- + ")");
+ + ", centerY = " + centerY + ", endCallback = "
+ + animationCallback + ", id = " + id + ")");
}
final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
- sendSpecToAnimation(mCurrentMagnificationSpec, endCallback);
+ sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
if (isMagnifying() && (id != INVALID_ID)) {
mIdOfLastServiceToMagnify = id;
}
@@ -875,7 +876,7 @@ public class FullScreenMagnificationController {
* the spec did not change
*/
public boolean reset(int displayId, boolean animate) {
- return reset(displayId, animate ? STUB_RUNNABLE : null);
+ return reset(displayId, animate ? STUB_ANIMATION_CALLBACK : null);
}
/**
@@ -883,18 +884,19 @@ public class FullScreenMagnificationController {
* transition.
*
* @param displayId The logical display id.
- * @param endCallback Called when the animation is ended or the spec did not change.
+ * @param animationCallback Called when the animation result is valid.
* {@code null} to transition immediately
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
- public boolean reset(int displayId, Runnable endCallback) {
+ public boolean reset(int displayId,
+ MagnificationAnimationCallback animationCallback) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.reset(endCallback);
+ return display.reset(animationCallback);
}
}
@@ -946,7 +948,7 @@ public class FullScreenMagnificationController {
return false;
}
return display.setScaleAndCenter(Float.NaN, centerX, centerY,
- animate ? STUB_RUNNABLE : null, id);
+ animate ? STUB_ANIMATION_CALLBACK : null, id);
}
}
@@ -970,7 +972,7 @@ public class FullScreenMagnificationController {
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
boolean animate, int id) {
return setScaleAndCenter(displayId, scale, centerX, centerY,
- transformToStubRunnable(animate), id);
+ transformToStubCallback(animate), id);
}
/**
@@ -984,20 +986,20 @@ public class FullScreenMagnificationController {
* center and scale, or {@link Float#NaN} to leave unchanged
* @param centerY the screen-relative Y coordinate around which to
* center and scale, or {@link Float#NaN} to leave unchanged
- * @param endCallback called when the transition is finished successfully or the spec did not
- * change. {@code null} to transition immediately.
+ * @param animationCallback Called when the animation result is valid.
+ * {@code null} to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
- Runnable endCallback, int id) {
+ MagnificationAnimationCallback animationCallback, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.setScaleAndCenter(scale, centerX, centerY, endCallback, id);
+ return display.setScaleAndCenter(scale, centerX, centerY, animationCallback, id);
}
}
@@ -1230,7 +1232,7 @@ public class FullScreenMagnificationController {
private final ValueAnimator mValueAnimator;
// Called when the callee wants animating and the sent spec matches the target spec.
- private Runnable mEndCallback;
+ private MagnificationAnimationCallback mAnimationCallback;
private final Object mLock;
private final int mDisplayId;
@@ -1268,33 +1270,35 @@ public class FullScreenMagnificationController {
}
}
- void updateSentSpecMainThread(MagnificationSpec spec, Runnable endCallback) {
+ void updateSentSpecMainThread(MagnificationSpec spec,
+ MagnificationAnimationCallback animationCallback) {
if (mValueAnimator.isRunning()) {
- // Avoid AnimationEnd Callback.
- mEndCallback = null;
mValueAnimator.cancel();
}
- mEndCallback = endCallback;
+ mAnimationCallback = animationCallback;
// If the current and sent specs don't match, update the sent spec.
synchronized (mLock) {
final boolean changed = !mSentMagnificationSpec.equals(spec);
if (changed) {
- if (mEndCallback != null) {
+ if (mAnimationCallback != null) {
animateMagnificationSpecLocked(spec);
} else {
setMagnificationSpecLocked(spec);
}
} else {
- sendEndCallbackMainThread();
+ sendEndCallbackMainThread(true);
}
}
}
- private void sendEndCallbackMainThread() {
- if (mEndCallback != null) {
- mEndCallback.run();
- mEndCallback = null;
+ private void sendEndCallbackMainThread(boolean success) {
+ if (mAnimationCallback != null) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "sendEndCallbackMainThread: " + success);
+ }
+ mAnimationCallback.onResult(success);
+ mAnimationCallback = null;
}
}
@@ -1337,17 +1341,16 @@ public class FullScreenMagnificationController {
@Override
public void onAnimationStart(Animator animation) {
-
}
@Override
public void onAnimationEnd(Animator animation) {
- sendEndCallbackMainThread();
+ sendEndCallbackMainThread(true);
}
@Override
public void onAnimationCancel(Animator animation) {
-
+ sendEndCallbackMainThread(false);
}
@Override
@@ -1481,7 +1484,7 @@ public class FullScreenMagnificationController {
}
@Nullable
- private static Runnable transformToStubRunnable(boolean animate) {
- return animate ? STUB_RUNNABLE : null;
+ private static MagnificationAnimationCallback transformToStubCallback(boolean animate) {
+ return animate ? STUB_ANIMATION_CALLBACK : null;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 57bfbf33d680..6acd9b6b3803 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -44,6 +44,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.os.Looper;
import android.view.MagnificationSpec;
+import android.view.accessibility.MagnificationAnimationCallback;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -99,12 +100,12 @@ public class FullScreenMagnificationControllerTest {
ValueAnimator.AnimatorListener mStateListener;
FullScreenMagnificationController mFullScreenMagnificationController;
- Runnable mEndCallback;
+ MagnificationAnimationCallback mAnimationCallback;
@Before
public void setUp() {
Looper looper = InstrumentationRegistry.getContext().getMainLooper();
- mEndCallback = Mockito.mock(Runnable.class);
+ mAnimationCallback = Mockito.mock(MagnificationAnimationCallback.class);
// Pretending ID of the Thread associated with looper as main thread ID in controller
when(mMockContext.getMainLooper()).thenReturn(looper);
when(mMockControllerCtx.getContext()).thenReturn(mMockContext);
@@ -323,7 +324,6 @@ public class FullScreenMagnificationControllerTest {
for (int i = 0; i < DISPLAY_COUNT; i++) {
setScaleAndCenter_animated_stateChangesAndAnimationHappens(i);
resetMockWindowManager();
- Mockito.reset(mEndCallback);
}
}
@@ -336,7 +336,7 @@ public class FullScreenMagnificationControllerTest {
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale,
- newCenter.x, newCenter.y, mEndCallback, SERVICE_ID_1));
+ newCenter.x, newCenter.y, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -365,18 +365,17 @@ public class FullScreenMagnificationControllerTest {
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
mStateListener.onAnimationEnd(mMockValueAnimator);
verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
- verify(mEndCallback).run();
+ verify(mAnimationCallback).onResult(true);
}
@Test
public void testSetScaleAndCenterWithAnimation_sameSpec_noAnimationButInvokeEndCallback() {
for (int i = 0; i < DISPLAY_COUNT; i++) {
- setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(i);
- Mockito.reset(mEndCallback);
+ setScaleAndCenter_sameSpec_noAnimationButInvokeCallbacks(i);
}
}
- private void setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(int displayId) {
+ private void setScaleAndCenter_sameSpec_noAnimationButInvokeCallbacks(int displayId) {
register(displayId);
final PointF center = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
final float targetScale = 2.0f;
@@ -385,11 +384,11 @@ public class FullScreenMagnificationControllerTest {
mMessageCapturingHandler.sendAllMessages();
assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- targetScale, center.x, center.y, mEndCallback, SERVICE_ID_1));
+ targetScale, center.x, center.y, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
verify(mMockValueAnimator, never()).start();
- verify(mEndCallback).run();
+ verify(mAnimationCallback).onResult(true);
}
@Test
@@ -673,38 +672,38 @@ public class FullScreenMagnificationControllerTest {
public void testReset_notMagnifying_noStateChangeButInvokeCallback() {
for (int i = 0; i < DISPLAY_COUNT; i++) {
reset_notMagnifying_noStateChangeButInvokeCallback(i);
- Mockito.reset(mEndCallback);
}
}
private void reset_notMagnifying_noStateChangeButInvokeCallback(int displayId) {
register(displayId);
- assertFalse(mFullScreenMagnificationController.reset(displayId, mEndCallback));
+ assertFalse(mFullScreenMagnificationController.reset(displayId, mAnimationCallback));
mMessageCapturingHandler.sendAllMessages();
verify(mMockAms, never()).notifyMagnificationChanged(eq(displayId),
any(Region.class), anyFloat(), anyFloat(), anyFloat());
- verify(mEndCallback).run();
+ verify(mAnimationCallback).onResult(true);
}
@Test
- public void testReset_Magnifying_resetsMagnificationAndInvokeLastEndCallback() {
+ public void testReset_Magnifying_resetsMagnificationAndInvokeCallbacks() {
for (int i = 0; i < DISPLAY_COUNT; i++) {
- reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(i);
+ reset_Magnifying_resetsMagnificationAndInvokeCallbacks(i);
}
}
- private void reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(int displayId) {
+ private void reset_Magnifying_resetsMagnificationAndInvokeCallbacks(int displayId) {
register(displayId);
float scale = 2.5f;
PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, firstCenter.x, firstCenter.y, mEndCallback, SERVICE_ID_1));
+ scale, firstCenter.x, firstCenter.y, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
Mockito.reset(mMockValueAnimator);
// Stubs the logic after the animation is started.
doAnswer(invocation -> {
+ mStateListener.onAnimationCancel(mMockValueAnimator);
mStateListener.onAnimationEnd(mMockValueAnimator);
return null;
}).when(mMockValueAnimator).cancel();
@@ -713,13 +712,14 @@ public class FullScreenMagnificationControllerTest {
float fraction = 0.33f;
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- Runnable lastEndCallback = Mockito.mock(Runnable.class);
+ MagnificationAnimationCallback lastAnimationCallback = Mockito.mock(
+ MagnificationAnimationCallback.class);
- assertTrue(mFullScreenMagnificationController.reset(displayId, lastEndCallback));
+ assertTrue(mFullScreenMagnificationController.reset(displayId, lastAnimationCallback));
mMessageCapturingHandler.sendAllMessages();
// Verify expected actions.
- verify(mEndCallback, never()).run();
+ verify(mAnimationCallback).onResult(false);
verify(mMockValueAnimator).start();
verify(mMockValueAnimator).cancel();
@@ -729,7 +729,7 @@ public class FullScreenMagnificationControllerTest {
mStateListener.onAnimationEnd(mMockValueAnimator);
assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_0));
- verify(lastEndCallback).run();
+ verify(lastAnimationCallback).onResult(true);
}
@Test
@@ -1142,6 +1142,7 @@ public class FullScreenMagnificationControllerTest {
verify(mMockValueAnimator).addListener(animatorListenerArgumentCaptor.capture());
mStateListener = animatorListenerArgumentCaptor.getValue();
Mockito.reset(mMockValueAnimator); // Ignore other initialization
+ Mockito.reset(mAnimationCallback);
}
private void zoomIn2xToMiddle(int displayId) {