Merge "Enable multi-display support for magnification controller"
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 35098a0..cebe6e12 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -37,6 +37,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.Display;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
@@ -382,7 +383,8 @@
void init(int connectionId, IBinder windowToken);
boolean onGesture(int gestureId);
boolean onKeyEvent(KeyEvent event);
- void onMagnificationChanged(@NonNull Region region,
+ /** Magnification changed callbacks for different displays */
+ void onMagnificationChanged(int displayId, @NonNull Region region,
float scale, float centerX, float centerY);
void onSoftKeyboardShowModeChanged(int showMode);
void onPerformGestureResult(int sequence, boolean completedSuccessfully);
@@ -452,7 +454,9 @@
private WindowManager mWindowManager;
- private MagnificationController mMagnificationController;
+ /** List of magnification controllers, mapping from displayId -> MagnificationController. */
+ private final SparseArray<MagnificationController> mMagnificationControllers =
+ new SparseArray<>(0);
private SoftKeyboardController mSoftKeyboardController;
private AccessibilityButtonController mAccessibilityButtonController;
@@ -483,8 +487,10 @@
* client code.
*/
private void dispatchServiceConnected() {
- if (mMagnificationController != null) {
- mMagnificationController.onServiceConnected();
+ synchronized (mLock) {
+ for (int i = 0; i < mMagnificationControllers.size(); i++) {
+ mMagnificationControllers.valueAt(i).onServiceConnectedLocked();
+ }
}
if (mSoftKeyboardController != null) {
mSoftKeyboardController.onServiceConnected();
@@ -652,11 +658,34 @@
*/
@NonNull
public final MagnificationController getMagnificationController() {
+ return getMagnificationController(Display.DEFAULT_DISPLAY);
+ }
+
+ /**
+ * Returns the magnification controller of specified logical display, which may be used to
+ * query and modify the state of display magnification.
+ * <p>
+ * <strong>Note:</strong> In order to control magnification, your service
+ * must declare the capability by setting the
+ * {@link android.R.styleable#AccessibilityService_canControlMagnification}
+ * property in its meta-data. For more information, see
+ * {@link #SERVICE_META_DATA}.
+ *
+ * @param displayId The logic display id, use {@link Display#DEFAULT_DISPLAY} for
+ * default display.
+ * @return the magnification controller
+ *
+ * @hide
+ */
+ @NonNull
+ public final MagnificationController getMagnificationController(int displayId) {
synchronized (mLock) {
- if (mMagnificationController == null) {
- mMagnificationController = new MagnificationController(this, mLock);
+ MagnificationController controller = mMagnificationControllers.get(displayId);
+ if (controller == null) {
+ controller = new MagnificationController(this, mLock, displayId);
+ mMagnificationControllers.put(displayId, controller);
}
- return mMagnificationController;
+ return controller;
}
}
@@ -765,11 +794,14 @@
}
}
- private void onMagnificationChanged(@NonNull Region region, float scale,
+ private void onMagnificationChanged(int displayId, @NonNull Region region, float scale,
float centerX, float centerY) {
- if (mMagnificationController != null) {
- mMagnificationController.dispatchMagnificationChanged(
- region, scale, centerX, centerY);
+ MagnificationController controller;
+ synchronized (mLock) {
+ controller = mMagnificationControllers.get(displayId);
+ }
+ if (controller != null) {
+ controller.dispatchMagnificationChanged(region, scale, centerX, centerY);
}
}
@@ -794,6 +826,7 @@
*/
public static final class MagnificationController {
private final AccessibilityService mService;
+ private final int mDisplayId;
/**
* Map of listeners to their handlers. Lazily created when adding the
@@ -802,19 +835,19 @@
private ArrayMap<OnMagnificationChangedListener, Handler> mListeners;
private final Object mLock;
- MagnificationController(@NonNull AccessibilityService service, @NonNull Object lock) {
+ MagnificationController(@NonNull AccessibilityService service, @NonNull Object lock,
+ int displayId) {
mService = service;
mLock = lock;
+ mDisplayId = displayId;
}
/**
* Called when the service is connected.
*/
- void onServiceConnected() {
- synchronized (mLock) {
- if (mListeners != null && !mListeners.isEmpty()) {
- setMagnificationCallbackEnabled(true);
- }
+ void onServiceConnectedLocked() {
+ if (mListeners != null && !mListeners.isEmpty()) {
+ setMagnificationCallbackEnabled(true);
}
}
@@ -891,7 +924,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- connection.setMagnificationCallbackEnabled(enabled);
+ connection.setMagnificationCallbackEnabled(mDisplayId, enabled);
} catch (RemoteException re) {
throw new RuntimeException(re);
}
@@ -952,7 +985,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.getMagnificationScale();
+ return connection.getMagnificationScale(mDisplayId);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to obtain scale", re);
re.rethrowFromSystemServer();
@@ -981,7 +1014,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.getMagnificationCenterX();
+ return connection.getMagnificationCenterX(mDisplayId);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to obtain center X", re);
re.rethrowFromSystemServer();
@@ -1010,7 +1043,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.getMagnificationCenterY();
+ return connection.getMagnificationCenterY(mDisplayId);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to obtain center Y", re);
re.rethrowFromSystemServer();
@@ -1044,7 +1077,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.getMagnificationRegion();
+ return connection.getMagnificationRegion(mDisplayId);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to obtain magnified region", re);
re.rethrowFromSystemServer();
@@ -1073,7 +1106,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.resetMagnification(animate);
+ return connection.resetMagnification(mDisplayId, animate);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to reset", re);
re.rethrowFromSystemServer();
@@ -1101,7 +1134,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.setMagnificationScaleAndCenter(
+ return connection.setMagnificationScaleAndCenter(mDisplayId,
scale, Float.NaN, Float.NaN, animate);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to set scale", re);
@@ -1133,7 +1166,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.setMagnificationScaleAndCenter(
+ return connection.setMagnificationScaleAndCenter(mDisplayId,
Float.NaN, centerX, centerY, animate);
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to set center", re);
@@ -1624,9 +1657,10 @@
}
@Override
- public void onMagnificationChanged(@NonNull Region region,
+ public void onMagnificationChanged(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
- AccessibilityService.this.onMagnificationChanged(region, scale, centerX, centerY);
+ AccessibilityService.this.onMagnificationChanged(displayId, region, scale,
+ centerX, centerY);
}
@Override
@@ -1729,13 +1763,15 @@
mCaller.sendMessage(message);
}
- public void onMagnificationChanged(@NonNull Region region,
+ /** Magnification changed callbacks for different displays */
+ public void onMagnificationChanged(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
final SomeArgs args = SomeArgs.obtain();
args.arg1 = region;
args.arg2 = scale;
args.arg3 = centerX;
args.arg4 = centerY;
+ args.argi1 = displayId;
final Message message = mCaller.obtainMessageO(DO_ON_MAGNIFICATION_CHANGED, args);
mCaller.sendMessage(message);
@@ -1865,7 +1901,10 @@
final float scale = (float) args.arg2;
final float centerX = (float) args.arg3;
final float centerY = (float) args.arg4;
- mCallback.onMagnificationChanged(region, scale, centerX, centerY);
+ final int displayId = args.argi1;
+ args.recycle();
+ mCallback.onMagnificationChanged(displayId, region, scale,
+ centerX, centerY);
}
} return;
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index 4e96b8f..1dae4fc 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -41,7 +41,7 @@
void onKeyEvent(in KeyEvent event, int sequence);
- void onMagnificationChanged(in Region region, float scale, float centerX, float centerY);
+ void onMagnificationChanged(int displayId, in Region region, float scale, float centerX, float centerY);
void onSoftKeyboardShowModeChanged(int showMode);
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 276131f..8c38fe4 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -70,20 +70,20 @@
oneway void setOnKeyEventResult(boolean handled, int sequence);
- float getMagnificationScale();
+ float getMagnificationScale(int displayId);
- float getMagnificationCenterX();
+ float getMagnificationCenterX(int displayId);
- float getMagnificationCenterY();
+ float getMagnificationCenterY(int displayId);
- Region getMagnificationRegion();
+ Region getMagnificationRegion(int displayId);
- boolean resetMagnification(boolean animate);
+ boolean resetMagnification(int displayId, boolean animate);
- boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
+ boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX, float centerY,
boolean animate);
- void setMagnificationCallbackEnabled(boolean enabled);
+ void setMagnificationCallbackEnabled(int displayId, boolean enabled);
boolean setSoftKeyboardShowMode(int showMode);
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 3f9627e..a021e3c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1240,7 +1240,7 @@
}
@Override
- public void onMagnificationChanged(@NonNull Region region,
+ public void onMagnificationChanged(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
/* do nothing */
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index 0dd7685..683d16b 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -88,32 +88,32 @@
public void setOnKeyEventResult(boolean handled, int sequence) {}
- public float getMagnificationScale() {
+ public float getMagnificationScale(int displayId) {
return 0.0f;
}
- public float getMagnificationCenterX() {
+ public float getMagnificationCenterX(int displayId) {
return 0.0f;
}
- public float getMagnificationCenterY() {
+ public float getMagnificationCenterY(int displayId) {
return 0.0f;
}
- public Region getMagnificationRegion() {
+ public Region getMagnificationRegion(int displayId) {
return null;
}
- public boolean resetMagnification(boolean animate) {
+ public boolean resetMagnification(int displayId, boolean animate) {
return false;
}
- public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
- boolean animate) {
+ public boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX,
+ float centerY, boolean animate) {
return false;
}
- public void setMagnificationCallbackEnabled(boolean enabled) {}
+ public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {}
public boolean setSoftKeyboardShowMode(int showMode) {
return false;
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 6eba914..2c075dc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -53,6 +53,7 @@
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
import com.android.server.accessibility.AccessibilityManagerService.RemoteAccessibilityConnection;
@@ -751,7 +752,7 @@
}
@Override
- public float getMagnificationScale() {
+ public float getMagnificationScale(int displayId) {
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return 1.0f;
@@ -759,14 +760,14 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- return mSystemSupport.getMagnificationController().getScale();
+ return mSystemSupport.getMagnificationController().getScale(displayId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
- public Region getMagnificationRegion() {
+ public Region getMagnificationRegion(int displayId) {
synchronized (mLock) {
final Region region = Region.obtain();
if (!isCalledForCurrentUserLocked()) {
@@ -775,22 +776,22 @@
MagnificationController magnificationController =
mSystemSupport.getMagnificationController();
boolean registeredJustForThisCall =
- registerMagnificationIfNeeded(magnificationController);
+ registerMagnificationIfNeeded(displayId, magnificationController);
final long identity = Binder.clearCallingIdentity();
try {
- magnificationController.getMagnificationRegion(region);
+ magnificationController.getMagnificationRegion(displayId, region);
return region;
} finally {
Binder.restoreCallingIdentity(identity);
if (registeredJustForThisCall) {
- magnificationController.unregister();
+ magnificationController.unregister(displayId);
}
}
}
}
@Override
- public float getMagnificationCenterX() {
+ public float getMagnificationCenterX(int displayId) {
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return 0.0f;
@@ -798,21 +799,21 @@
MagnificationController magnificationController =
mSystemSupport.getMagnificationController();
boolean registeredJustForThisCall =
- registerMagnificationIfNeeded(magnificationController);
+ registerMagnificationIfNeeded(displayId, magnificationController);
final long identity = Binder.clearCallingIdentity();
try {
- return magnificationController.getCenterX();
+ return magnificationController.getCenterX(displayId);
} finally {
Binder.restoreCallingIdentity(identity);
if (registeredJustForThisCall) {
- magnificationController.unregister();
+ magnificationController.unregister(displayId);
}
}
}
}
@Override
- public float getMagnificationCenterY() {
+ public float getMagnificationCenterY(int displayId) {
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return 0.0f;
@@ -820,31 +821,31 @@
MagnificationController magnificationController =
mSystemSupport.getMagnificationController();
boolean registeredJustForThisCall =
- registerMagnificationIfNeeded(magnificationController);
+ registerMagnificationIfNeeded(displayId, magnificationController);
final long identity = Binder.clearCallingIdentity();
try {
- return magnificationController.getCenterY();
+ return magnificationController.getCenterY(displayId);
} finally {
Binder.restoreCallingIdentity(identity);
if (registeredJustForThisCall) {
- magnificationController.unregister();
+ magnificationController.unregister(displayId);
}
}
}
}
- private boolean registerMagnificationIfNeeded(
+ private boolean registerMagnificationIfNeeded(int displayId,
MagnificationController magnificationController) {
- if (!magnificationController.isRegisteredLocked()
+ if (!magnificationController.isRegistered(displayId)
&& mSecurityPolicy.canControlMagnification(this)) {
- magnificationController.register();
+ magnificationController.register(displayId);
return true;
}
return false;
}
@Override
- public boolean resetMagnification(boolean animate) {
+ public boolean resetMagnification(int displayId, boolean animate) {
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
@@ -857,16 +858,16 @@
try {
MagnificationController magnificationController =
mSystemSupport.getMagnificationController();
- return (magnificationController.reset(animate)
- || !magnificationController.isMagnifying());
+ return (magnificationController.reset(displayId, animate)
+ || !magnificationController.isMagnifying(displayId));
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
- public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
- boolean animate) {
+ public boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX,
+ float centerY, boolean animate) {
synchronized (mLock) {
if (!isCalledForCurrentUserLocked()) {
return false;
@@ -878,11 +879,11 @@
try {
MagnificationController magnificationController =
mSystemSupport.getMagnificationController();
- if (!magnificationController.isRegisteredLocked()) {
- magnificationController.register();
+ if (!magnificationController.isRegistered(displayId)) {
+ magnificationController.register(displayId);
}
return magnificationController
- .setScaleAndCenter(scale, centerX, centerY, animate, mId);
+ .setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -890,12 +891,12 @@
}
@Override
- public void setMagnificationCallbackEnabled(boolean enabled) {
- mInvocationHandler.setMagnificationCallbackEnabled(enabled);
+ public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
+ mInvocationHandler.setMagnificationCallbackEnabled(displayId, enabled);
}
- public boolean isMagnificationCallbackEnabled() {
- return mInvocationHandler.mIsMagnificationCallbackEnabled;
+ public boolean isMagnificationCallbackEnabled(int displayId) {
+ return mInvocationHandler.isMagnificationCallbackEnabled(displayId);
}
@Override
@@ -1106,10 +1107,10 @@
InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
}
- public void notifyMagnificationChangedLocked(@NonNull Region region,
+ public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
mInvocationHandler
- .notifyMagnificationChangedLocked(region, scale, centerX, centerY);
+ .notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
}
public void notifySoftKeyboardShowModeChangedLocked(int showState) {
@@ -1128,12 +1129,12 @@
* Called by the invocation handler to notify the service that the
* state of magnification has changed.
*/
- private void notifyMagnificationChangedInternal(@NonNull Region region,
+ private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
if (listener != null) {
try {
- listener.onMagnificationChanged(region, scale, centerX, centerY);
+ listener.onMagnificationChanged(displayId, region, scale, centerX, centerY);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
}
@@ -1251,7 +1252,9 @@
private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7;
private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8;
- private boolean mIsMagnificationCallbackEnabled = false;
+ /** List of magnification callback states, mapping from displayId -> Boolean */
+ @GuardedBy("mlock")
+ private final SparseArray<Boolean> mMagnificationCallbackState = new SparseArray<>(0);
private boolean mIsSoftKeyboardCallbackEnabled = false;
public InvocationHandler(Looper looper) {
@@ -1277,7 +1280,8 @@
final float scale = (float) args.arg2;
final float centerX = (float) args.arg3;
final float centerY = (float) args.arg4;
- notifyMagnificationChangedInternal(region, scale, centerX, centerY);
+ final int displayId = args.argi1;
+ notifyMagnificationChangedInternal(displayId, region, scale, centerX, centerY);
args.recycle();
} break;
@@ -1301,11 +1305,12 @@
}
}
- public void notifyMagnificationChangedLocked(@NonNull Region region, float scale,
- float centerX, float centerY) {
- if (!mIsMagnificationCallbackEnabled) {
- // Callback is disabled, don't bother packing args.
- return;
+ public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
+ float scale, float centerX, float centerY) {
+ synchronized (mLock) {
+ if (mMagnificationCallbackState.get(displayId) == null) {
+ return;
+ }
}
final SomeArgs args = SomeArgs.obtain();
@@ -1313,13 +1318,26 @@
args.arg2 = scale;
args.arg3 = centerX;
args.arg4 = centerY;
+ args.argi1 = displayId;
final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
msg.sendToTarget();
}
- public void setMagnificationCallbackEnabled(boolean enabled) {
- mIsMagnificationCallbackEnabled = enabled;
+ public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
+ synchronized (mLock) {
+ if (enabled) {
+ mMagnificationCallbackState.put(displayId, true);
+ } else {
+ mMagnificationCallbackState.remove(displayId);
+ }
+ }
+ }
+
+ public boolean isMagnificationCallbackEnabled(int displayId) {
+ synchronized (mLock) {
+ return mMagnificationCallbackState.get(displayId) != null;
+ }
}
public void notifySoftKeyboardShowModeChangedLocked(int showState) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 763c16f..dbe86c1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -208,6 +208,8 @@
private final WindowManagerInternal mWindowManagerService;
+ private final DisplayManager mDisplayManager;
+
private AppWidgetManagerInternal mAppWidgetService;
private final SecurityPolicy mSecurityPolicy;
@@ -304,10 +306,12 @@
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mMainHandler = new MainHandler(mContext.getMainLooper());
mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
+ mDisplayManager = mContext.getSystemService(DisplayManager.class);
registerBroadcastReceivers();
new AccessibilityContentObserver(mMainHandler).register(
context.getContentResolver());
+ registerDisplayListener(mMainHandler);
}
@Override
@@ -523,6 +527,30 @@
}, UserHandle.ALL, intentFilter, null, null);
}
+ private void registerDisplayListener(Handler handler) {
+ mDisplayManager.registerDisplayListener(new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ synchronized (mLock) {
+ UserState userState = getCurrentUserStateLocked();
+ updateMagnificationLocked(userState);
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ if (mMagnificationController != null) {
+ mMagnificationController.onDisplayRemoved(displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ // do nothing
+ }
+ }, handler);
+ }
+
@Override
public long addClient(IAccessibilityManagerClient callback, int userId) {
synchronized (mLock) {
@@ -968,17 +996,18 @@
* Called by the MagnificationController when the state of display
* magnification changes.
*
+ * @param displayId The logical display id.
* @param region the new magnified region, may be empty if
* magnification is not enabled (e.g. scale is 1)
* @param scale the new scale
* @param centerX the new screen-relative center X coordinate
* @param centerY the new screen-relative center Y coordinate
*/
- public void notifyMagnificationChanged(@NonNull Region region,
+ public void notifyMagnificationChanged(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
synchronized (mLock) {
notifyClearAccessibilityCacheLocked();
- notifyMagnificationChangedLocked(region, scale, centerX, centerY);
+ notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
}
}
@@ -1203,12 +1232,12 @@
}
}
- private void notifyMagnificationChangedLocked(@NonNull Region region,
+ private void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
float scale, float centerX, float centerY) {
final UserState state = getCurrentUserStateLocked();
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = state.mBoundServices.get(i);
- service.notifyMagnificationChangedLocked(region, scale, centerX, centerY);
+ service.notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
}
}
@@ -2191,15 +2220,44 @@
return;
}
- if (!mUiAutomationManager.suppressingAccessibilityServicesLocked()
- && (userState.mIsDisplayMagnificationEnabled
- || userState.mIsNavBarMagnificationEnabled
- || userHasListeningMagnificationServicesLocked(userState))) {
- // Initialize the magnification controller if necessary
- getMagnificationController();
- mMagnificationController.register();
- } else if (mMagnificationController != null) {
- mMagnificationController.unregister();
+ if (mUiAutomationManager.suppressingAccessibilityServicesLocked()
+ && mMagnificationController != null) {
+ mMagnificationController.unregisterAll();
+ return;
+ }
+
+ // register all display if global magnification is enabled.
+ final Display[] displays = mDisplayManager.getDisplays();
+ if (userState.mIsDisplayMagnificationEnabled
+ || userState.mIsNavBarMagnificationEnabled) {
+ for (int i = 0; i < displays.length; i++) {
+ final Display display = displays[i];
+ // Overlay display uses overlay window to simulate secondary displays in
+ // one display. It's not a real display and there's no input events for it.
+ // We should ignore it.
+ if (display.getType() == Display.TYPE_OVERLAY) {
+ continue;
+ }
+ getMagnificationController().register(display.getDisplayId());
+ }
+ return;
+ }
+
+ // register if display has listening magnification services.
+ for (int i = 0; i < displays.length; i++) {
+ final Display display = displays[i];
+ // Overlay display uses overlay window to simulate secondary displays in
+ // one display. It's not a real display and there's no input events for it.
+ // We should ignore it.
+ if (display.getType() == Display.TYPE_OVERLAY) {
+ continue;
+ }
+ final int displayId = display.getDisplayId();
+ if (userHasListeningMagnificationServicesLocked(userState, displayId)) {
+ getMagnificationController().register(displayId);
+ } else if (mMagnificationController != null) {
+ mMagnificationController.unregister(displayId);
+ }
}
}
@@ -2222,12 +2280,13 @@
* Returns whether the specified user has any services that are capable of
* controlling magnification and are actively listening for magnification updates.
*/
- private boolean userHasListeningMagnificationServicesLocked(UserState userState) {
+ private boolean userHasListeningMagnificationServicesLocked(UserState userState,
+ int displayId) {
final List<AccessibilityServiceConnection> services = userState.mBoundServices;
for (int i = 0, count = services.size(); i < count; i++) {
final AccessibilityServiceConnection service = services.get(i);
if (mSecurityPolicy.canControlMagnification(service)
- && service.isMagnificationCallbackEnabled()) {
+ && service.isMagnificationCallbackEnabled(displayId)) {
return true;
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 86132a8..a19a847 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -109,7 +109,7 @@
UserState userState = mUserStateWeakReference.get();
if (userState == null) return;
userState.removeServiceLocked(this);
- mSystemSupport.getMagnificationController().resetIfNeeded(mId);
+ mSystemSupport.getMagnificationController().resetAllIfNeeded(mId);
resetLocked();
}
@@ -256,7 +256,7 @@
userState.serviceDisconnectedLocked(this);
}
resetLocked();
- mSystemSupport.getMagnificationController().resetIfNeeded(mId);
+ mSystemSupport.getMagnificationController().resetAllIfNeeded(mId);
mSystemSupport.onClientChangeLocked(false);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index 6a97fbb..e784056 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -19,7 +19,6 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -32,6 +31,7 @@
import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.Display;
import android.view.MagnificationSpec;
import android.view.View;
@@ -39,6 +39,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.wm.WindowManagerInternal;
@@ -68,9 +69,7 @@
private final Object mLock;
- private final AccessibilityManagerService mAms;
-
- private final SettingsBridge mSettingsBridge;
+ private final ControllerContext mControllerCtx;
private final ScreenStateObserver mScreenStateObserver;
@@ -78,11 +77,9 @@
private final long mMainThreadId;
- private Handler mHandler;
-
- private final WindowManagerInternal mWindowManager;
-
- private final DisplayMagnification mDisplay;
+ /** List of display Magnification, mapping from displayId -> DisplayMagnification. */
+ @GuardedBy("mLock")
+ private final SparseArray<DisplayMagnification> mDisplays = new SparseArray<>(0);
/**
* This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
@@ -107,46 +104,82 @@
// Flag indicating that we are registered with window manager.
private boolean mRegistered;
private boolean mUnregisterPending;
+ private boolean mDeleteAfterUnregister;
private final int mDisplayId;
private static final int INVALID_ID = -1;
private int mIdOfLastServiceToMagnify = INVALID_ID;
-
- DisplayMagnification(int displayId, SpecAnimationBridge specAnimation) {
+ DisplayMagnification(int displayId) {
mDisplayId = displayId;
- mSpecAnimationBridge = specAnimation;
+ mSpecAnimationBridge = new SpecAnimationBridge(mControllerCtx, mLock, mDisplayId);
}
- void register() {
- synchronized (mLock) {
- if (!mRegistered) {
- mWindowManager.setMagnificationCallbacks(this);
- mSpecAnimationBridge.setEnabled(true);
- // Obtain initial state.
- mWindowManager.getMagnificationRegion(mMagnificationRegion);
- mMagnificationRegion.getBounds(mMagnificationBounds);
- mRegistered = true;
- }
+ /**
+ * Registers magnification callback and get current magnification region from
+ * window manager.
+ *
+ * @return true if callback registers successful.
+ */
+ @GuardedBy("mLock")
+ boolean register() {
+ mRegistered = mControllerCtx.getWindowManager().setMagnificationCallbacks(
+ mDisplayId, this);
+ if (!mRegistered) {
+ Slog.w(LOG_TAG, "set magnification callbacks fail, displayId:" + mDisplayId);
+ return false;
}
+ mSpecAnimationBridge.setEnabled(true);
+ // Obtain initial state.
+ mControllerCtx.getWindowManager().getMagnificationRegion(
+ mDisplayId, mMagnificationRegion);
+ mMagnificationRegion.getBounds(mMagnificationBounds);
+ return true;
}
- void unregister() {
- synchronized (mLock) {
- if (!isMagnifying()) {
- unregisterInternalLocked();
- } else {
- mUnregisterPending = true;
- reset(true);
- }
+ /**
+ * Unregisters magnification callback from window manager. Callbacks to
+ * {@link MagnificationController#unregisterCallbackLocked(int, boolean)} after
+ * unregistered.
+ *
+ * @param delete true if this instance should be removed from the SparseArray in
+ * MagnificationController after unregistered, for example, display removed.
+ */
+ @GuardedBy("mLock")
+ void unregister(boolean delete) {
+ if (mRegistered) {
+ mSpecAnimationBridge.setEnabled(false);
+ mControllerCtx.getWindowManager().setMagnificationCallbacks(
+ mDisplayId, null);
+ mMagnificationRegion.setEmpty();
+ mRegistered = false;
+ unregisterCallbackLocked(mDisplayId, delete);
}
+ mUnregisterPending = false;
}
- boolean isRegisteredLocked() {
+ /**
+ * Reset magnification status with animation enabled. {@link #unregister(boolean)} will be
+ * called after animation finished.
+ *
+ * @param delete true if this instance should be removed from the SparseArray in
+ * MagnificationController after unregistered, for example, display removed.
+ */
+ @GuardedBy("mLock")
+ void unregisterPending(boolean delete) {
+ mDeleteAfterUnregister = delete;
+ mUnregisterPending = true;
+ reset(true);
+ }
+
+ boolean isRegistered() {
return mRegistered;
}
+ boolean isMagnifying() {
+ return mCurrentMagnificationSpec.scale > 1.0f;
+ }
float getScale() {
return mCurrentMagnificationSpec.scale;
@@ -156,18 +189,20 @@
return mCurrentMagnificationSpec.offsetX;
}
- float getCenterX() {
- synchronized (mLock) {
- return (mMagnificationBounds.width() / 2.0f
- + mMagnificationBounds.left - getOffsetX()) / getScale();
- }
+ float getOffsetY() {
+ return mCurrentMagnificationSpec.offsetY;
}
+ @GuardedBy("mLock")
+ float getCenterX() {
+ return (mMagnificationBounds.width() / 2.0f
+ + mMagnificationBounds.left - getOffsetX()) / getScale();
+ }
+
+ @GuardedBy("mLock")
float getCenterY() {
- synchronized (mLock) {
- return (mMagnificationBounds.height() / 2.0f
- + mMagnificationBounds.top - getOffsetY()) / getScale();
- }
+ return (mMagnificationBounds.height() / 2.0f
+ + mMagnificationBounds.top - getOffsetY()) / getScale();
}
/**
@@ -203,64 +238,35 @@
return mSpecAnimationBridge.mSentMagnificationSpec.offsetY;
}
- boolean resetIfNeeded(boolean animate) {
- synchronized (mLock) {
- if (isMagnifying()) {
- reset(animate);
- return true;
- }
- return false;
- }
- }
-
- float getOffsetY() {
- return mCurrentMagnificationSpec.offsetY;
- }
-
- boolean isMagnifying() {
- return mCurrentMagnificationSpec.scale > 1.0f;
- }
-
- void unregisterInternalLocked() {
- if (mRegistered) {
- mSpecAnimationBridge.setEnabled(false);
- mWindowManager.setMagnificationCallbacks(null);
- mMagnificationRegion.setEmpty();
-
- mRegistered = false;
- }
- mUnregisterPending = false;
- }
-
-
@Override
public void onMagnificationRegionChanged(Region magnificationRegion) {
final Message m = PooledLambda.obtainMessage(
- DisplayMagnification.this::updateMagnificationRegion,
+ DisplayMagnification::updateMagnificationRegion, this,
Region.obtain(magnificationRegion));
- mHandler.sendMessage(m);
+ mControllerCtx.getHandler().sendMessage(m);
}
@Override
public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
final Message m = PooledLambda.obtainMessage(
- DisplayMagnification.this::requestRectangleOnScreen, left, top, right, bottom);
- mHandler.sendMessage(m);
+ DisplayMagnification::requestRectangleOnScreen, this,
+ left, top, right, bottom);
+ mControllerCtx.getHandler().sendMessage(m);
}
@Override
public void onRotationChanged(int rotation) {
// Treat as context change and reset
- final Message m = PooledLambda.obtainMessage(DisplayMagnification.this::resetIfNeeded,
- true);
- mHandler.sendMessage(m);
+ final Message m = PooledLambda.obtainMessage(MagnificationController::resetIfNeeded,
+ MagnificationController.this, mDisplayId, true);
+ mControllerCtx.getHandler().sendMessage(m);
}
@Override
public void onUserContextChanged() {
- final Message m = PooledLambda.obtainMessage(DisplayMagnification.this::resetIfNeeded,
- true);
- mHandler.sendMessage(m);
+ final Message m = PooledLambda.obtainMessage(MagnificationController::resetIfNeeded,
+ MagnificationController.this, mDisplayId, true);
+ mControllerCtx.getHandler().sendMessage(m);
}
/**
@@ -298,8 +304,9 @@
mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
} else {
final Message m = PooledLambda.obtainMessage(
- this.mSpecAnimationBridge::updateSentSpecMainThread, spec, animate);
- mHandler.sendMessage(m);
+ SpecAnimationBridge::updateSentSpecMainThread,
+ mSpecAnimationBridge, spec, animate);
+ mControllerCtx.getHandler().sendMessage(m);
}
}
@@ -313,30 +320,26 @@
}
void onMagnificationChangedLocked() {
- mAms.notifyMagnificationChanged(mMagnificationRegion,
+ mControllerCtx.getAms().notifyMagnificationChanged(mDisplayId, mMagnificationRegion,
getScale(), getCenterX(), getCenterY());
if (mUnregisterPending && !isMagnifying()) {
- unregisterInternalLocked();
+ unregister(mDeleteAfterUnregister);
}
}
+ @GuardedBy("mLock")
boolean magnificationRegionContains(float x, float y) {
- synchronized (mLock) {
- return mMagnificationRegion.contains((int) x, (int) y);
-
- }
+ return mMagnificationRegion.contains((int) x, (int) y);
}
+ @GuardedBy("mLock")
void getMagnificationBounds(@NonNull Rect outBounds) {
- synchronized (mLock) {
- outBounds.set(mMagnificationBounds);
- }
+ outBounds.set(mMagnificationBounds);
}
+ @GuardedBy("mLock")
void getMagnificationRegion(@NonNull Region outRegion) {
- synchronized (mLock) {
- outRegion.set(mMagnificationRegion);
- }
+ outRegion.set(mMagnificationRegion);
}
void requestRectangleOnScreen(int left, int top, int right, int bottom) {
@@ -392,94 +395,76 @@
outFrame.scale(1.0f / scale);
}
- /**
- * Resets magnification if last magnifying service is disabled.
- *
- * @param connectionId the connection ID be disabled.
- * @return {@code true} on success, {@code false} on failure
- */
- boolean resetIfNeeded(int connectionId) {
- if (mIdOfLastServiceToMagnify == connectionId) {
- return resetIfNeeded(true /*animate*/);
- }
- return false;
- }
-
+ @GuardedBy("mLock")
void setForceShowMagnifiableBounds(boolean show) {
if (mRegistered) {
- mWindowManager.setForceShowMagnifiableBounds(show);
+ mControllerCtx.getWindowManager().setForceShowMagnifiableBounds(
+ mDisplayId, show);
}
}
+ @GuardedBy("mLock")
boolean reset(boolean animate) {
- synchronized (mLock) {
- if (!mRegistered) {
- return false;
- }
- final MagnificationSpec spec = mCurrentMagnificationSpec;
- final boolean changed = !spec.isNop();
- if (changed) {
- spec.clear();
- onMagnificationChangedLocked();
- }
- mIdOfLastServiceToMagnify = INVALID_ID;
- sendSpecToAnimation(spec, animate);
- return changed;
+ if (!mRegistered) {
+ return false;
}
+ final MagnificationSpec spec = mCurrentMagnificationSpec;
+ final boolean changed = !spec.isNop();
+ if (changed) {
+ spec.clear();
+ onMagnificationChangedLocked();
+ }
+ mIdOfLastServiceToMagnify = INVALID_ID;
+ sendSpecToAnimation(spec, animate);
+ return changed;
}
-
+ @GuardedBy("mLock")
boolean setScale(float scale, float pivotX, float pivotY,
boolean animate, int id) {
-
- synchronized (mLock) {
- if (!mRegistered) {
- return false;
- }
- // Constrain scale immediately for use in the pivot calculations.
- scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
-
- final Rect viewport = mTempRect;
- mMagnificationRegion.getBounds(viewport);
- final MagnificationSpec spec = mCurrentMagnificationSpec;
- final float oldScale = spec.scale;
- final float oldCenterX
- = (viewport.width() / 2.0f - spec.offsetX + viewport.left) / oldScale;
- final float oldCenterY
- = (viewport.height() / 2.0f - spec.offsetY + viewport.top) / oldScale;
- final float normPivotX = (pivotX - spec.offsetX) / oldScale;
- final float normPivotY = (pivotY - spec.offsetY) / oldScale;
- final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
- final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
- final float centerX = normPivotX + offsetX;
- final float centerY = normPivotY + offsetY;
- mIdOfLastServiceToMagnify = id;
-
- return setScaleAndCenter(scale, centerX, centerY, animate, id);
+ if (!mRegistered) {
+ return false;
}
+ // Constrain scale immediately for use in the pivot calculations.
+ scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+
+ final Rect viewport = mTempRect;
+ mMagnificationRegion.getBounds(viewport);
+ final MagnificationSpec spec = mCurrentMagnificationSpec;
+ final float oldScale = spec.scale;
+ final float oldCenterX =
+ (viewport.width() / 2.0f - spec.offsetX + viewport.left) / oldScale;
+ final float oldCenterY =
+ (viewport.height() / 2.0f - spec.offsetY + viewport.top) / oldScale;
+ final float normPivotX = (pivotX - spec.offsetX) / oldScale;
+ final float normPivotY = (pivotY - spec.offsetY) / oldScale;
+ final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
+ final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
+ final float centerX = normPivotX + offsetX;
+ final float centerY = normPivotY + offsetY;
+ mIdOfLastServiceToMagnify = id;
+ return setScaleAndCenter(scale, centerX, centerY, animate, id);
}
+ @GuardedBy("mLock")
boolean setScaleAndCenter(float scale, float centerX, float centerY,
boolean animate, int id) {
-
- synchronized (mLock) {
- if (!mRegistered) {
- return false;
- }
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
- + ", centerY = " + centerY + ", animate = " + animate
- + ", id = " + id
- + ")");
- }
- final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
- sendSpecToAnimation(mCurrentMagnificationSpec, animate);
- if (isMagnifying() && (id != INVALID_ID)) {
- mIdOfLastServiceToMagnify = id;
- }
- return changed;
+ if (!mRegistered) {
+ return false;
}
+ if (DEBUG) {
+ Slog.i(LOG_TAG,
+ "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
+ + ", centerY = " + centerY + ", animate = " + animate
+ + ", id = " + id
+ + ")");
+ }
+ final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
+ sendSpecToAnimation(mCurrentMagnificationSpec, animate);
+ if (isMagnifying() && (id != INVALID_ID)) {
+ mIdOfLastServiceToMagnify = id;
+ }
+ return changed;
}
/**
@@ -527,22 +512,21 @@
return changed;
}
+ @GuardedBy("mLock")
void offsetMagnifiedRegion(float offsetX, float offsetY, int id) {
- synchronized (mLock) {
- if (!mRegistered) {
- return;
- }
-
- final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
- final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
- if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
- onMagnificationChangedLocked();
- }
- if (id != INVALID_ID) {
- mIdOfLastServiceToMagnify = id;
- }
- sendSpecToAnimation(mCurrentMagnificationSpec, false);
+ if (!mRegistered) {
+ return;
}
+
+ final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
+ final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
+ if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
+ onMagnificationChangedLocked();
+ }
+ if (id != INVALID_ID) {
+ mIdOfLastServiceToMagnify = id;
+ }
+ sendSpecToAnimation(mCurrentMagnificationSpec, false);
}
boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
@@ -593,44 +577,38 @@
@Override
public String toString() {
- return "DisplayMagnification{" +
- "mCurrentMagnificationSpec=" + mCurrentMagnificationSpec +
- ", mMagnificationRegion=" + mMagnificationRegion +
- ", mMagnificationBounds=" + mMagnificationBounds +
- ", mDisplayId=" + mDisplayId +
- ", mUserId=" + mUserId +
- ", mIdOfLastServiceToMagnify=" + mIdOfLastServiceToMagnify +
- ", mRegistered=" + mRegistered +
- ", mUnregisterPending=" + mUnregisterPending +
- '}';
+ return "DisplayMagnification["
+ + "mCurrentMagnificationSpec=" + mCurrentMagnificationSpec
+ + ", mMagnificationRegion=" + mMagnificationRegion
+ + ", mMagnificationBounds=" + mMagnificationBounds
+ + ", mDisplayId=" + mDisplayId
+ + ", mIdOfLastServiceToMagnify=" + mIdOfLastServiceToMagnify
+ + ", mRegistered=" + mRegistered
+ + ", mUnregisterPending=" + mUnregisterPending
+ + ']';
}
-
}
- public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
- this(context, ams, lock, null, LocalServices.getService(WindowManagerInternal.class),
- new ValueAnimator(), new SettingsBridge(context.getContentResolver()));
- mHandler = new Handler(context.getMainLooper());
+ /**
+ * MagnificationController Constructor
+ */
+ public MagnificationController(@NonNull Context context,
+ @NonNull AccessibilityManagerService ams, @NonNull Object lock) {
+ this(new ControllerContext(context, ams,
+ LocalServices.getService(WindowManagerInternal.class),
+ new Handler(context.getMainLooper()),
+ context.getResources().getInteger(R.integer.config_longAnimTime)), lock);
}
- public MagnificationController(
- Context context,
- AccessibilityManagerService ams,
- Object lock,
- Handler handler,
- WindowManagerInternal windowManagerInternal,
- ValueAnimator valueAnimator,
- SettingsBridge settingsBridge) {
- mHandler = handler;
- mWindowManager = windowManagerInternal;
- mMainThreadId = context.getMainLooper().getThread().getId();
- mAms = ams;
- mScreenStateObserver = new ScreenStateObserver(context, this);
+ /**
+ * Constructor for tests
+ */
+ @VisibleForTesting
+ public MagnificationController(@NonNull ControllerContext ctx, @NonNull Object lock) {
+ mControllerCtx = ctx;
mLock = lock;
- mSettingsBridge = settingsBridge;
- //TODO (multidisplay): Magnification is supported only for the default display.
- mDisplay = new DisplayMagnification(Display.DEFAULT_DISPLAY,
- new SpecAnimationBridge(context, mLock, mWindowManager, valueAnimator));
+ mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
+ mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
}
/**
@@ -639,54 +617,114 @@
*
* This tracking imposes a cost on the system, so we avoid tracking this data unless it's
* required.
+ *
+ * @param displayId The logical display id.
*/
- public void register() {
+ public void register(int displayId) {
synchronized (mLock) {
- mScreenStateObserver.register();
+ DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ display = new DisplayMagnification(displayId);
+ }
+ if (display.isRegistered()) {
+ return;
+ }
+ if (display.register()) {
+ mDisplays.put(displayId, display);
+ mScreenStateObserver.registerIfNecessary();
+ }
}
- mDisplay.register();
}
/**
* Stop requiring tracking the magnification region. We may remain registered while we
* reset magnification.
- */
- public void unregister() {
- synchronized (mLock) {
- mScreenStateObserver.unregister();
- }
- mDisplay.unregister();
- }
-
- /**
- * Check if we are registered. Note that we may be planning to unregister at any moment.
*
- * @return {@code true} if the controller is registered. {@code false} otherwise.
+ * @param displayId The logical display id.
*/
- public boolean isRegisteredLocked() {
- return mDisplay.isRegisteredLocked();
+ public void unregister(int displayId) {
+ synchronized (mLock) {
+ unregisterLocked(displayId, false);
+ }
}
/**
+ * Stop tracking all displays' magnification region.
+ */
+ public void unregisterAll() {
+ synchronized (mLock) {
+ // display will be removed from array after unregister, we need to clone it to
+ // prevent error.
+ final SparseArray<DisplayMagnification> displays = mDisplays.clone();
+ for (int i = 0; i < displays.size(); i++) {
+ unregisterLocked(displays.keyAt(i), false);
+ }
+ }
+ }
+
+ /**
+ * Remove the display magnification with given id.
+ *
+ * @param displayId The logical display id.
+ */
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mLock) {
+ unregisterLocked(displayId, true);
+ }
+ }
+
+ /**
+ * Check if we are registered on specified display. Note that we may be planning to unregister
+ * at any moment.
+ *
+ * @return {@code true} if the controller is registered on specified display.
+ * {@code false} otherwise.
+ *
+ * @param displayId The logical display id.
+ */
+ public boolean isRegistered(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.isRegistered();
+ }
+ }
+
+ /**
+ * @param displayId The logical display id.
* @return {@code true} if magnification is active, e.g. the scale
* is > 1, {@code false} otherwise
*/
- public boolean isMagnifying() {
- return mDisplay.isMagnifying();
+ public boolean isMagnifying(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.isMagnifying();
+ }
}
/**
* Returns whether the magnification region contains the specified
* screen-relative coordinates.
*
+ * @param displayId The logical display id.
* @param x the screen-relative X coordinate to check
* @param y the screen-relative Y coordinate to check
* @return {@code true} if the coordinate is contained within the
* magnified region, or {@code false} otherwise
*/
- public boolean magnificationRegionContains(float x, float y) {
- return mDisplay.magnificationRegionContains(x, y);
-
+ public boolean magnificationRegionContains(int displayId, float x, float y) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.magnificationRegionContains(x, y);
+ }
}
/**
@@ -694,11 +732,18 @@
* magnification region. If magnification is not enabled, the returned
* bounds will be empty.
*
+ * @param displayId The logical display id.
* @param outBounds rect to populate with the bounds of the magnified
* region
*/
- public void getMagnificationBounds(@NonNull Rect outBounds) {
- mDisplay.getMagnificationBounds(outBounds);
+ public void getMagnificationBounds(int displayId, @NonNull Rect outBounds) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ display.getMagnificationBounds(outBounds);
+ }
}
/**
@@ -706,76 +751,122 @@
* region. If magnification is not enabled, then the returned region
* will be empty.
*
+ * @param displayId The logical display id.
* @param outRegion the region to populate
*/
- public void getMagnificationRegion(@NonNull Region outRegion) {
- mDisplay.getMagnificationRegion(outRegion);
+ public void getMagnificationRegion(int displayId, @NonNull Region outRegion) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ display.getMagnificationRegion(outRegion);
+ }
}
/**
* Returns the magnification scale. If an animation is in progress,
* this reflects the end state of the animation.
*
+ * @param displayId The logical display id.
* @return the scale
*/
- public float getScale() {
- return mDisplay.getScale();
+ public float getScale(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return 1.0f;
+ }
+ return display.getScale();
+ }
}
/**
* Returns the X offset of the magnification viewport. If an animation
* is in progress, this reflects the end state of the animation.
*
+ * @param displayId The logical display id.
* @return the X offset
*/
- public float getOffsetX() {
- return mDisplay.getOffsetX();
+ public float getOffsetX(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return 0.0f;
+ }
+ return display.getOffsetX();
+ }
}
-
/**
* Returns the screen-relative X coordinate of the center of the
* magnification viewport.
*
+ * @param displayId The logical display id.
* @return the X coordinate
*/
- public float getCenterX() {
- return mDisplay.getCenterX();
+ public float getCenterX(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return 0.0f;
+ }
+ return display.getCenterX();
+ }
}
/**
* Returns the Y offset of the magnification viewport. If an animation
* is in progress, this reflects the end state of the animation.
*
+ * @param displayId The logical display id.
* @return the Y offset
*/
- public float getOffsetY() {
- return mDisplay.getOffsetY();
+ public float getOffsetY(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return 0.0f;
+ }
+ return display.getOffsetY();
+ }
}
/**
* Returns the screen-relative Y coordinate of the center of the
* magnification viewport.
*
+ * @param displayId The logical display id.
* @return the Y coordinate
*/
- public float getCenterY() {
- return mDisplay.getCenterY();
+ public float getCenterY(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return 0.0f;
+ }
+ return display.getCenterY();
+ }
}
/**
* Resets the magnification scale and center, optionally animating the
* transition.
*
+ * @param displayId The logical display id.
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
- public boolean reset(boolean animate) {
-
- return mDisplay.reset(animate);
-
+ public boolean reset(int displayId, boolean animate) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.reset(animate);
+ }
}
/**
@@ -783,6 +874,7 @@
* optionally animating the transition. If animation is disabled, the
* transition is immediate.
*
+ * @param displayId The logical display id.
* @param scale the target scale, must be >= 1
* @param pivotX the screen-relative X coordinate around which to scale
* @param pivotY the screen-relative Y coordinate around which to scale
@@ -792,15 +884,22 @@
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
- public boolean setScale(float scale, float pivotX, float pivotY, boolean animate, int id) {
- return mDisplay.
- setScale(scale, pivotX, pivotY, animate, id);
+ public boolean setScale(int displayId, float scale, float pivotX, float pivotY,
+ boolean animate, int id) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.setScale(scale, pivotX, pivotY, animate, id);
+ }
}
/**
* Sets the center of the magnified region, optionally animating the
* transition. If animation is disabled, the transition is immediate.
*
+ * @param displayId The logical display id.
* @param centerX the screen-relative X coordinate around which to
* center
* @param centerY the screen-relative Y coordinate around which to
@@ -811,9 +910,14 @@
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
- public boolean setCenter(float centerX, float centerY, boolean animate, int id) {
- return mDisplay.
- setScaleAndCenter(Float.NaN, centerX, centerY, animate, id);
+ public boolean setCenter(int displayId, float centerX, float centerY, boolean animate, int id) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.setScaleAndCenter(Float.NaN, centerX, centerY, animate, id);
+ }
}
/**
@@ -821,6 +925,7 @@
* animating the transition. If animation is disabled, the transition
* is immediate.
*
+ * @param displayId The logical display id.
* @param scale the target scale, or {@link Float#NaN} to leave unchanged
* @param centerX the screen-relative X coordinate around which to
* center and scale, or {@link Float#NaN} to leave unchanged
@@ -832,53 +937,66 @@
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
- public boolean setScaleAndCenter(
- float scale, float centerX, float centerY, boolean animate, int id) {
- return mDisplay.
- setScaleAndCenter(scale, centerX, centerY, animate, id);
+ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+ boolean animate, int id) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return false;
+ }
+ return display.setScaleAndCenter(scale, centerX, centerY, animate, id);
+ }
}
/**
* Offsets the magnified region. Note that the offsetX and offsetY values actually move in the
* opposite direction as the offsets passed in here.
*
+ * @param displayId The logical display id.
* @param offsetX the amount in pixels to offset the region in the X direction, in current
* screen pixels.
* @param offsetY the amount in pixels to offset the region in the Y direction, in current
* screen pixels.
* @param id the ID of the service requesting the change
*/
- public void offsetMagnifiedRegion(float offsetX, float offsetY, int id) {
- mDisplay.offsetMagnifiedRegion(offsetX, offsetY,
- id);
+ public void offsetMagnifiedRegion(int displayId, float offsetX, float offsetY, int id) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ display.offsetMagnifiedRegion(offsetX, offsetY, id);
+ }
}
/**
* Get the ID of the last service that changed the magnification spec.
*
+ * @param displayId The logical display id.
* @return The id
*/
- public int getIdOfLastServiceToMagnify() {
- return mDisplay.getIdOfLastServiceToMagnify();
+ public int getIdOfLastServiceToMagnify(int displayId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return -1;
+ }
+ return display.getIdOfLastServiceToMagnify();
+ }
}
/**
- * Persists the current magnification scale to the current user's settings.
+ * Persists the default display magnification scale to the current user's settings.
*/
public void persistScale() {
- persistScale(Display.DEFAULT_DISPLAY);
- }
- /**
- * Persists the current magnification scale to the current user's settings.
- */
- public void persistScale(int displayId) {
- final float scale = mDisplay.getScale();
+ // TODO: b/123047354, Need support multi-display?
+ final float scale = getScale(Display.DEFAULT_DISPLAY);
final int userId = mUserId;
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
- mSettingsBridge.putMagnificationScale(scale, displayId, userId);
+ mControllerCtx.putMagnificationScale(scale, userId);
return null;
}
}.execute();
@@ -892,7 +1010,7 @@
* scale if none is available
*/
public float getPersistedScale() {
- return mSettingsBridge.getMagnificationScale(Display.DEFAULT_DISPLAY, mUserId);
+ return mControllerCtx.getMagnificationScale(mUserId);
}
/**
@@ -901,50 +1019,136 @@
* @param userId the currently active user ID
*/
public void setUserId(int userId) {
- if (mUserId != userId) {
- mUserId = userId;
+ if (mUserId == userId) {
+ return;
+ }
+ mUserId = userId;
+ resetAllIfNeeded(false);
+ }
- synchronized (mLock) {
- if (isMagnifying()) {
- reset(false);
- }
+ /**
+ * Resets all displays' magnification if last magnifying service is disabled.
+ *
+ * @param connectionId
+ */
+ public void resetAllIfNeeded(int connectionId) {
+ synchronized (mLock) {
+ for (int i = 0; i < mDisplays.size(); i++) {
+ resetIfNeeded(mDisplays.keyAt(i), connectionId);
}
}
}
- /**
+ /**
* Resets magnification if magnification and auto-update are both enabled.
*
+ * @param displayId The logical display id.
* @param animate whether the animate the transition
- * @return whether was {@link #isMagnifying magnifying}
+ * @return whether was {@link #isMagnifying(int) magnifying}
*/
- public boolean resetIfNeeded(boolean animate) {
- return mDisplay.resetIfNeeded(animate);
+ boolean resetIfNeeded(int displayId, boolean animate) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null || !display.isMagnifying()) {
+ return false;
+ }
+ display.reset(animate);
+ return true;
+ }
}
/**
* Resets magnification if last magnifying service is disabled.
*
+ * @param displayId The logical display id.
* @param connectionId the connection ID be disabled.
* @return {@code true} on success, {@code false} on failure
*/
- public boolean resetIfNeeded(int connectionId) {
- return mDisplay.resetIfNeeded(connectionId);
+ boolean resetIfNeeded(int displayId, int connectionId) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null || !display.isMagnifying()
+ || connectionId != display.getIdOfLastServiceToMagnify()) {
+ return false;
+ }
+ display.reset(true);
+ return true;
+ }
}
- void setForceShowMagnifiableBounds(boolean show) {
- mDisplay.setForceShowMagnifiableBounds(show);
+ void setForceShowMagnifiableBounds(int displayId, boolean show) {
+ synchronized (mLock) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ display.setForceShowMagnifiableBounds(show);
+ }
}
private void onScreenTurnedOff() {
final Message m = PooledLambda.obtainMessage(
- mDisplay::resetIfNeeded, false);
- mHandler.sendMessage(m);
+ MagnificationController::resetAllIfNeeded, this, false);
+ mControllerCtx.getHandler().sendMessage(m);
+ }
+
+ private void resetAllIfNeeded(boolean animate) {
+ synchronized (mLock) {
+ for (int i = 0; i < mDisplays.size(); i++) {
+ resetIfNeeded(mDisplays.keyAt(i), animate);
+ }
+ }
+ }
+
+ private void unregisterLocked(int displayId, boolean delete) {
+ final DisplayMagnification display = mDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ if (!display.isRegistered()) {
+ if (delete) {
+ mDisplays.remove(displayId);
+ }
+ return;
+ }
+ if (!display.isMagnifying()) {
+ display.unregister(delete);
+ } else {
+ display.unregisterPending(delete);
+ }
+ }
+
+ /**
+ * Callbacks from DisplayMagnification after display magnification unregistered. It will remove
+ * DisplayMagnification instance if delete is true, and unregister screen state if
+ * there is no registered display magnification.
+ */
+ private void unregisterCallbackLocked(int displayId, boolean delete) {
+ if (delete) {
+ mDisplays.remove(displayId);
+ }
+ // unregister screen state if necessary
+ boolean hasRegister = false;
+ for (int i = 0; i < mDisplays.size(); i++) {
+ final DisplayMagnification display = mDisplays.valueAt(i);
+ hasRegister = display.isRegistered();
+ if (hasRegister) {
+ break;
+ }
+ }
+ if (!hasRegister) {
+ mScreenStateObserver.unregister();
+ }
}
@Override
public String toString() {
- return mDisplay.toString();
+ StringBuilder builder = new StringBuilder();
+ builder.append("MagnificationController[");
+ builder.append("mUserId=").append(mUserId);
+ builder.append(", mDisplays=").append(mDisplays);
+ builder.append("]");
+ return builder.toString();
}
/**
@@ -952,7 +1156,7 @@
* updates to the window manager.
*/
private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener {
- private final WindowManagerInternal mWindowManager;
+ private final ControllerContext mControllerCtx;
/**
* The magnification spec that was sent to the window manager. This should
@@ -973,16 +1177,17 @@
private final Object mLock;
+ private final int mDisplayId;
+
@GuardedBy("mLock")
private boolean mEnabled = false;
- private SpecAnimationBridge(Context context, Object lock, WindowManagerInternal wm,
- ValueAnimator animator) {
+ private SpecAnimationBridge(ControllerContext ctx, Object lock, int displayId) {
+ mControllerCtx = ctx;
mLock = lock;
- mWindowManager = wm;
- final long animationDuration = context.getResources().getInteger(
- R.integer.config_longAnimTime);
- mValueAnimator = animator;
+ mDisplayId = displayId;
+ final long animationDuration = mControllerCtx.getAnimationDuration();
+ mValueAnimator = mControllerCtx.newValueAnimator();
mValueAnimator.setDuration(animationDuration);
mValueAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
mValueAnimator.setFloatValues(0.0f, 1.0f);
@@ -999,7 +1204,8 @@
mEnabled = enabled;
if (!mEnabled) {
mSentMagnificationSpec.clear();
- mWindowManager.setMagnificationSpec(mSentMagnificationSpec);
+ mControllerCtx.getWindowManager().setMagnificationSpec(
+ mDisplayId, mSentMagnificationSpec);
}
}
}
@@ -1031,7 +1237,8 @@
}
mSentMagnificationSpec.setTo(spec);
- mWindowManager.setMagnificationSpec(spec);
+ mControllerCtx.getWindowManager().setMagnificationSpec(
+ mDisplayId, mSentMagnificationSpec);
}
}
@@ -1054,9 +1261,7 @@
mTmpMagnificationSpec.offsetY = mStartMagnificationSpec.offsetY +
(mEndMagnificationSpec.offsetY - mStartMagnificationSpec.offsetY)
* fract;
- synchronized (mLock) {
- setMagnificationSpecLocked(mTmpMagnificationSpec);
- }
+ setMagnificationSpecLocked(mTmpMagnificationSpec);
}
}
}
@@ -1072,7 +1277,7 @@
mController = controller;
}
- public void register() {
+ public void registerIfNecessary() {
if (!mRegistered) {
mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
mRegistered = true;
@@ -1092,26 +1297,97 @@
}
}
- // Extra class to get settings so tests can mock it
- public static class SettingsBridge {
- private final ContentResolver mContentResolver;
+ /**
+ * This class holds resources used between the classes in MagnificationController, and
+ * functions for tests to mock it.
+ */
+ @VisibleForTesting
+ public static class ControllerContext {
+ private final Context mContext;
+ private final AccessibilityManagerService mAms;
+ private final WindowManagerInternal mWindowManager;
+ private final Handler mHandler;
+ private final Long mAnimationDuration;
- public SettingsBridge(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
+ /**
+ * Constructor for ControllerContext.
+ */
+ public ControllerContext(@NonNull Context context,
+ @NonNull AccessibilityManagerService ams,
+ @NonNull WindowManagerInternal windowManager,
+ @NonNull Handler handler,
+ long animationDuration) {
+ mContext = context;
+ mAms = ams;
+ mWindowManager = windowManager;
+ mHandler = handler;
+ mAnimationDuration = animationDuration;
}
- public void putMagnificationScale(float value, int displayId, int userId) {
- Settings.Secure.putFloatForUser(mContentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE + (
- Display.DEFAULT_DISPLAY == displayId ? "" : displayId),
- value, userId);
+ /**
+ * @return A context.
+ */
+ @NonNull
+ public Context getContext() {
+ return mContext;
}
- public float getMagnificationScale(int displayId, int userId) {
- return Settings.Secure.getFloatForUser(mContentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE
- + (Display.DEFAULT_DISPLAY == displayId ? "" : displayId),
+ /**
+ * @return AccessibilityManagerService
+ */
+ @NonNull
+ public AccessibilityManagerService getAms() {
+ return mAms;
+ }
+
+ /**
+ * @return WindowManagerInternal
+ */
+ @NonNull
+ public WindowManagerInternal getWindowManager() {
+ return mWindowManager;
+ }
+
+ /**
+ * @return Handler for main looper
+ */
+ @NonNull
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ /**
+ * Create a new ValueAnimator.
+ *
+ * @return ValueAnimator
+ */
+ @NonNull
+ public ValueAnimator newValueAnimator() {
+ return new ValueAnimator();
+ }
+
+ /**
+ * Write Settings of magnification scale.
+ */
+ public void putMagnificationScale(float value, int userId) {
+ Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, value, userId);
+ }
+
+ /**
+ * Get Settings of magnification scale.
+ */
+ public float getMagnificationScale(int userId) {
+ return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
DEFAULT_MAGNIFICATION_SCALE, userId);
}
+
+ /**
+ * @return Configuration of animation duration.
+ */
+ public long getAnimationDuration() {
+ return mAnimationDuration;
+ }
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 80049e8..35abfd4 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -43,6 +43,7 @@
import android.util.MathUtils;
import android.util.Slog;
import android.util.TypedValue;
+import android.view.Display;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
@@ -251,14 +252,16 @@
mScreenStateReceiver.unregister();
}
// Check if need to reset when MagnificationGestureHandler is the last magnifying service.
- mMagnificationController.resetIfNeeded(
+ mMagnificationController.resetAllIfNeeded(
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
clearAndTransitionToStateDetecting();
}
void notifyShortcutTriggered() {
if (mDetectShortcutTrigger) {
- boolean wasMagnifying = mMagnificationController.resetIfNeeded(/* animate */ true);
+ // TODO: multi-display support for magnification gesture handler
+ boolean wasMagnifying = mMagnificationController.resetIfNeeded(Display.DEFAULT_DISPLAY,
+ /* animate */ true);
if (wasMagnifying) {
clearAndTransitionToStateDetecting();
} else {
@@ -419,8 +422,9 @@
Slog.i(LOG_TAG, "Panned content by scrollX: " + distanceX
+ " scrollY: " + distanceY);
}
- mMagnificationController.offsetMagnifiedRegion(distanceX, distanceY,
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ // TODO: multi-display support for magnification gesture handler
+ mMagnificationController.offsetMagnifiedRegion(Display.DEFAULT_DISPLAY, distanceX,
+ distanceY, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
return /* event consumed: */ true;
}
@@ -436,7 +440,8 @@
return mScaling;
}
- final float initialScale = mMagnificationController.getScale();
+ // TODO: multi-display support for magnification gesture handler
+ final float initialScale = mMagnificationController.getScale(Display.DEFAULT_DISPLAY);
final float targetScale = initialScale * detector.getScaleFactor();
// Don't allow a gesture to move the user further outside the
@@ -458,7 +463,8 @@
final float pivotX = detector.getFocusX();
final float pivotY = detector.getFocusY();
if (DEBUG_PANNING_SCALING) Slog.i(LOG_TAG, "Scaled content to: " + scale + "x");
- mMagnificationController.setScale(scale, pivotX, pivotY, false,
+ // TODO: multi-display support for magnification gesture handler
+ mMagnificationController.setScale(Display.DEFAULT_DISPLAY, scale, pivotX, pivotY, false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
return /* handled: */ true;
}
@@ -518,8 +524,10 @@
}
final float eventX = event.getX();
final float eventY = event.getY();
- if (mMagnificationController.magnificationRegionContains(eventX, eventY)) {
- mMagnificationController.setCenter(eventX, eventY,
+ // TODO: multi-display support for magnification gesture handler
+ if (mMagnificationController.magnificationRegionContains(
+ Display.DEFAULT_DISPLAY, eventX, eventY)) {
+ mMagnificationController.setCenter(Display.DEFAULT_DISPLAY, eventX, eventY,
/* animate */ mLastMoveOutsideMagnifiedRegion,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mLastMoveOutsideMagnifiedRegion = false;
@@ -657,8 +665,9 @@
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+ // TODO: multi-display support for magnification gesture handler
if (!mMagnificationController.magnificationRegionContains(
- event.getX(), event.getY())) {
+ Display.DEFAULT_DISPLAY, event.getX(), event.getY())) {
transitionToDelegatingStateAndClear();
@@ -671,7 +680,8 @@
// If magnified, delay an ACTION_DOWN for mMultiTapMaxDelay
// to ensure reachability of
// STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
- || mMagnificationController.isMagnifying()) {
+ // TODO: multi-display support for magnification gesture handler
+ || mMagnificationController.isMagnifying(Display.DEFAULT_DISPLAY)) {
afterMultiTapTimeoutTransitionToDelegatingState();
@@ -683,7 +693,8 @@
}
break;
case ACTION_POINTER_DOWN: {
- if (mMagnificationController.isMagnifying()) {
+ // TODO: multi-display support for magnification gesture handler
+ if (mMagnificationController.isMagnifying(Display.DEFAULT_DISPLAY)) {
transitionTo(mPanningScalingState);
clear();
} else {
@@ -712,8 +723,9 @@
mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
+ // TODO: multi-display support for magnification gesture handler
if (!mMagnificationController.magnificationRegionContains(
- event.getX(), event.getY())) {
+ Display.DEFAULT_DISPLAY, event.getX(), event.getY())) {
transitionToDelegatingStateAndClear();
@@ -864,7 +876,8 @@
clear();
// Toggle zoom
- if (mMagnificationController.isMagnifying()) {
+ // TODO: multi-display support for magnification gesture handler
+ if (mMagnificationController.isMagnifying(Display.DEFAULT_DISPLAY)) {
zoomOff();
} else {
zoomOn(up.getX(), up.getY());
@@ -876,8 +889,9 @@
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()");
clear();
+ // TODO: multi-display support for magnification gesture handler
mViewportDraggingState.mZoomedInBeforeDrag =
- mMagnificationController.isMagnifying();
+ mMagnificationController.isMagnifying(Display.DEFAULT_DISPLAY);
zoomOn(down.getX(), down.getY());
@@ -904,7 +918,8 @@
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "setShortcutTriggered(" + state + ")");
mShortcutTriggered = state;
- mMagnificationController.setForceShowMagnifiableBounds(state);
+ // TODO: multi-display support for magnification gesture handler
+ mMagnificationController.setForceShowMagnifiableBounds(Display.DEFAULT_DISPLAY, state);
}
}
@@ -914,7 +929,8 @@
final float scale = MathUtils.constrain(
mMagnificationController.getPersistedScale(),
MIN_SCALE, MAX_SCALE);
- mMagnificationController.setScaleAndCenter(
+ // TODO: multi-display support for magnification gesture handler
+ mMagnificationController.setScaleAndCenter(Display.DEFAULT_DISPLAY,
scale, centerX, centerY,
/* animate */ true,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
@@ -922,8 +938,8 @@
private void zoomOff() {
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "zoomOff()");
-
- mMagnificationController.reset(/* animate */ true);
+ // TODO: multi-display support for magnification gesture handler
+ mMagnificationController.reset(Display.DEFAULT_DISPLAY, /* animate */ true);
}
private static MotionEvent recycleAndNullify(@Nullable MotionEvent event) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index caebf15..545b69b 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -49,6 +49,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
+import android.view.Display;
import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
@@ -83,23 +84,36 @@
mService = service;
}
- private DisplayMagnifier mDisplayMagnifier;
+ private SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>();
private WindowsForAccessibilityObserver mWindowsForAccessibilityObserver;
- public void setMagnificationCallbacksLocked(MagnificationCallbacks callbacks) {
+ public boolean setMagnificationCallbacksLocked(int displayId,
+ MagnificationCallbacks callbacks) {
+ boolean result = false;
if (callbacks != null) {
- if (mDisplayMagnifier != null) {
+ if (mDisplayMagnifiers.get(displayId) != null) {
throw new IllegalStateException("Magnification callbacks already set!");
}
- mDisplayMagnifier = new DisplayMagnifier(mService, callbacks);
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
+ if (dc != null) {
+ final Display display = dc.getDisplay();
+ if (display != null && display.getType() != Display.TYPE_OVERLAY) {
+ mDisplayMagnifiers.put(displayId, new DisplayMagnifier(
+ mService, dc, display, callbacks));
+ result = true;
+ }
+ }
} else {
- if (mDisplayMagnifier == null) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier == null) {
throw new IllegalStateException("Magnification callbacks already cleared!");
}
- mDisplayMagnifier.destroyLocked();
- mDisplayMagnifier = null;
+ displayMagnifier.destroyLocked();
+ mDisplayMagnifiers.remove(displayId);
+ result = true;
}
+ return result;
}
public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
@@ -129,58 +143,72 @@
}
}
- public void setMagnificationSpecLocked(MagnificationSpec spec) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.setMagnificationSpecLocked(spec);
+ public void setMagnificationSpecLocked(int displayId, MagnificationSpec spec) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.setMagnificationSpecLocked(spec);
}
- if (mWindowsForAccessibilityObserver != null) {
+ // TODO: support multi-display for windows observer
+ if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
}
}
- public void getMagnificationRegionLocked(Region outMagnificationRegion) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.getMagnificationRegionLocked(outMagnificationRegion);
+ public void getMagnificationRegionLocked(int displayId, Region outMagnificationRegion) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.getMagnificationRegionLocked(outMagnificationRegion);
}
}
- public void onRectangleOnScreenRequestedLocked(Rect rectangle) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle);
+ public void onRectangleOnScreenRequestedLocked(int displayId, Rect rectangle) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.onRectangleOnScreenRequestedLocked(rectangle);
}
// Not relevant for the window observer.
}
- public void onWindowLayersChangedLocked() {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.onWindowLayersChangedLocked();
+ public void onWindowLayersChangedLocked(int displayId) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.onWindowLayersChangedLocked();
}
- if (mWindowsForAccessibilityObserver != null) {
+ // TODO: support multi-display for windows observer
+ if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
}
}
public void onRotationChangedLocked(DisplayContent displayContent) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.onRotationChangedLocked(displayContent);
+ final int displayId = displayContent.getDisplayId();
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.onRotationChangedLocked(displayContent);
}
- if (mWindowsForAccessibilityObserver != null) {
+ // TODO: support multi-display for windows observer
+ if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
}
}
public void onAppWindowTransitionLocked(WindowState windowState, int transition) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.onAppWindowTransitionLocked(windowState, transition);
+ final int displayId = windowState.getDisplayId();
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.onAppWindowTransitionLocked(windowState, transition);
}
// Not relevant for the window observer.
}
public void onWindowTransitionLocked(WindowState windowState, int transition) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.onWindowTransitionLocked(windowState, transition);
+ final int displayId = windowState.getDisplayId();
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.onWindowTransitionLocked(windowState, transition);
}
- if (mWindowsForAccessibilityObserver != null) {
+ // TODO: support multi-display for windows observer
+ if (mWindowsForAccessibilityObserver != null && displayId == Display.DEFAULT_DISPLAY) {
mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked();
}
}
@@ -197,7 +225,6 @@
}
}
-
public void onSomeWindowResizedOrMovedLocked() {
// Not relevant for the display magnifier.
@@ -207,29 +234,34 @@
}
/** NOTE: This has to be called within a surface transaction. */
- public void drawMagnifiedRegionBorderIfNeededLocked() {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
+ public void drawMagnifiedRegionBorderIfNeededLocked(int displayId) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
}
// Not relevant for the window observer.
}
public MagnificationSpec getMagnificationSpecForWindowLocked(WindowState windowState) {
- if (mDisplayMagnifier != null) {
- return mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState);
+ final int displayId = windowState.getDisplayId();
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ return displayMagnifier.getMagnificationSpecForWindowLocked(windowState);
}
return null;
}
public boolean hasCallbacksLocked() {
- return (mDisplayMagnifier != null
+ // TODO: support multi-display for windows observer
+ return (mDisplayMagnifiers.size() > 0
|| mWindowsForAccessibilityObserver != null);
}
- public void setForceShowMagnifiableBoundsLocked(boolean show) {
- if (mDisplayMagnifier != null) {
- mDisplayMagnifier.setForceShowMagnifiableBoundsLocked(show);
- mDisplayMagnifier.showMagnificationBoundsIfNeeded();
+ public void setForceShowMagnifiableBoundsLocked(int displayId, boolean show) {
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier != null) {
+ displayMagnifier.setForceShowMagnifiableBoundsLocked(show);
+ displayMagnifier.showMagnificationBoundsIfNeeded();
}
}
@@ -263,6 +295,8 @@
private final WindowManagerService mService;
private final MagnifiedViewport mMagnifedViewport;
private final Handler mHandler;
+ private final DisplayContent mDisplayContent;
+ private final Display mDisplay;
private final MagnificationCallbacks mCallbacks;
@@ -271,10 +305,14 @@
private boolean mForceShowMagnifiableBounds = false;
public DisplayMagnifier(WindowManagerService windowManagerService,
+ DisplayContent displayContent,
+ Display display,
MagnificationCallbacks callbacks) {
mContext = windowManagerService.mContext;
mService = windowManagerService;
mCallbacks = callbacks;
+ mDisplayContent = displayContent;
+ mDisplay = display;
mHandler = new MyHandler(mService.mH.getLooper());
mMagnifedViewport = new MagnifiedViewport();
mLongAnimationDuration = mContext.getResources().getInteger(
@@ -285,7 +323,7 @@
mMagnifedViewport.updateMagnificationSpecLocked(spec);
mMagnifedViewport.recomputeBoundsLocked();
- mService.applyMagnificationSpec(spec);
+ mService.applyMagnificationSpecLocked(mDisplay.getDisplayId(), spec);
mService.scheduleAnimationLocked();
}
@@ -482,7 +520,7 @@
if (mContext.getResources().getConfiguration().isScreenRound()) {
mCircularPath = new Path();
- mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
+ mDisplay.getRealSize(mTempPoint);
final int centerXY = mTempPoint.x / 2;
mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
} else {
@@ -512,7 +550,7 @@
}
public void recomputeBoundsLocked() {
- mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
+ mDisplay.getRealSize(mTempPoint);
final int screenWidth = mTempPoint.x;
final int screenHeight = mTempPoint.y;
@@ -671,9 +709,8 @@
}
private void populateWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
- final DisplayContent dc = mService.getDefaultDisplayContentLocked();
mTempLayer = 0;
- dc.forAllWindows((w) -> {
+ mDisplayContent.forAllWindows((w) -> {
if (w.isOnScreen() && w.isVisibleLw()
&& (w.mAttrs.alpha != 0)
&& !w.mWinAnimator.mEnterAnimationPending) {
@@ -703,8 +740,9 @@
public ViewportWindow(Context context) {
SurfaceControl surfaceControl = null;
try {
- mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
- surfaceControl = mService.getDefaultDisplayContentLocked().makeOverlay()
+ mDisplay.getRealSize(mTempPoint);
+ surfaceControl = mDisplayContent
+ .makeOverlay()
.setName(SURFACE_TITLE)
.setBufferSize(mTempPoint.x, mTempPoint.y) // not a typo
.setFormat(PixelFormat.TRANSLUCENT)
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 711ca00..9361e7f 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -25,7 +25,6 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -591,9 +590,7 @@
delayed = runningAppAnimation = true;
}
final WindowState window = findMainWindow();
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (window != null && accessibilityController != null
- && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
+ if (window != null && accessibilityController != null) {
accessibilityController.onAppWindowTransitionLocked(window, transit);
}
changed = true;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8026a04..ac1159a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1466,11 +1466,9 @@
}
}
- // TODO (multi-display): Magnification is supported only for the default display.
// Announce rotation only if we will not animate as we already have the
// windows in final state. Otherwise, we make this call at the rotation end.
- if (screenRotationAnimation == null && mWmService.mAccessibilityController != null
- && isDefaultDisplay) {
+ if (screenRotationAnimation == null && mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onRotationChangedLocked(this);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index b8a0739..b8db98b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -167,13 +167,11 @@
screenRotationAnimation.kill();
displayAnimator.mScreenRotationAnimation = null;
- //TODO (multidisplay): Accessibility supported only for the default
// display.
- if (accessibilityController != null && dc.isDefaultDisplay) {
+ if (accessibilityController != null) {
// We just finished rotation animation which means we did not
// announce the rotation and waited for it to end, announce now.
- accessibilityController.onRotationChangedLocked(
- mService.getDefaultDisplayContentLocked());
+ accessibilityController.onRotationChangedLocked(dc);
}
}
}
@@ -197,9 +195,8 @@
screenRotationAnimation.updateSurfaces(mTransaction);
}
orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (accessibilityController != null && dc.isDefaultDisplay) {
- accessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
+ if (accessibilityController != null) {
+ accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 1691dc0..5267e7e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -212,34 +212,40 @@
* and has access to the raw window data while the accessibility layer serves
* as a controller.
*
+ * @param displayId The logical display id.
* @param callbacks The callbacks to invoke.
+ * @return {@code false} if display id is not valid.
*/
- public abstract void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks);
+ public abstract boolean setMagnificationCallbacks(int displayId,
+ @Nullable MagnificationCallbacks callbacks);
/**
* Set by the accessibility layer to specify the magnification and panning to
* be applied to all windows that should be magnified.
*
+ * @param displayId The logical display id.
* @param spec The MagnficationSpec to set.
*
- * @see #setMagnificationCallbacks(MagnificationCallbacks)
+ * @see #setMagnificationCallbacks(int, MagnificationCallbacks)
*/
- public abstract void setMagnificationSpec(MagnificationSpec spec);
+ public abstract void setMagnificationSpec(int displayId, MagnificationSpec spec);
/**
* Set by the accessibility framework to indicate whether the magnifiable regions of the display
* should be shown.
*
+ * @param displayId The logical display id.
* @param show {@code true} to show magnifiable region bounds, {@code false} to hide
*/
- public abstract void setForceShowMagnifiableBounds(boolean show);
+ public abstract void setForceShowMagnifiableBounds(int displayId, boolean show);
/**
* Obtains the magnification regions.
*
+ * @param displayId The logical display id.
* @param magnificationRegion the current magnification region
*/
- public abstract void getMagnificationRegion(@NonNull Region magnificationRegion);
+ public abstract void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion);
/**
* Gets the magnification and translation applied to a window given its token.
@@ -251,7 +257,7 @@
*
* @return The magnification spec for the window.
*
- * @see #setMagnificationCallbacks(MagnificationCallbacks)
+ * @see #setMagnificationCallbacks(int, MagnificationCallbacks)
*/
public abstract MagnificationSpec getCompatibleMagnificationSpecForWindow(
IBinder windowToken);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index efb38f5..c8c834f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1846,9 +1846,9 @@
synchronized (mGlobalLock) {
if (mAccessibilityController != null) {
WindowState window = mWindowMap.get(token);
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (window != null && window.getDisplayId() == DEFAULT_DISPLAY) {
- mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
+ if (window != null) {
+ mAccessibilityController.onRectangleOnScreenRequestedLocked(
+ window.getDisplayId(), rectangle);
}
}
}
@@ -2237,8 +2237,7 @@
win.mDestroying = true;
win.destroySurface(false, stopped);
}
- // TODO(multidisplay): Magnification is supported only for the default display.
- if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
+ if (mAccessibilityController != null) {
mAccessibilityController.onWindowTransitionLocked(win, transit);
}
@@ -6823,10 +6822,10 @@
}
@Override
- public void setMagnificationSpec(MagnificationSpec spec) {
+ public void setMagnificationSpec(int displayId, MagnificationSpec spec) {
synchronized (mGlobalLock) {
if (mAccessibilityController != null) {
- mAccessibilityController.setMagnificationSpecLocked(spec);
+ mAccessibilityController.setMagnificationSpecLocked(displayId, spec);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
}
@@ -6837,10 +6836,10 @@
}
@Override
- public void setForceShowMagnifiableBounds(boolean show) {
+ public void setForceShowMagnifiableBounds(int displayId, boolean show) {
synchronized (mGlobalLock) {
if (mAccessibilityController != null) {
- mAccessibilityController.setForceShowMagnifiableBoundsLocked(show);
+ mAccessibilityController.setForceShowMagnifiableBoundsLocked(displayId, show);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
}
@@ -6848,10 +6847,11 @@
}
@Override
- public void getMagnificationRegion(@NonNull Region magnificationRegion) {
+ public void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion) {
synchronized (mGlobalLock) {
if (mAccessibilityController != null) {
- mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
+ mAccessibilityController.getMagnificationRegionLocked(displayId,
+ magnificationRegion);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
}
@@ -6879,16 +6879,19 @@
}
@Override
- public void setMagnificationCallbacks(@Nullable MagnificationCallbacks callbacks) {
+ public boolean setMagnificationCallbacks(int displayId,
+ @Nullable MagnificationCallbacks callbacks) {
synchronized (mGlobalLock) {
if (mAccessibilityController == null) {
mAccessibilityController = new AccessibilityController(
WindowManagerService.this);
}
- mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
+ boolean result = mAccessibilityController.setMagnificationCallbacksLocked(
+ displayId, callbacks);
if (!mAccessibilityController.hasCallbacksLocked()) {
mAccessibilityController = null;
}
+ return result;
}
}
@@ -7267,8 +7270,12 @@
}, false /* traverseTopToBottom */);
}
- public void applyMagnificationSpec(MagnificationSpec spec) {
- getDefaultDisplayContentLocked().applyMagnificationSpec(spec);
+ /** Called from Accessibility Controller to apply magnification spec */
+ public void applyMagnificationSpecLocked(int displayId, MagnificationSpec spec) {
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent != null) {
+ displayContent.applyMagnificationSpec(spec);
+ }
}
SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8f86c00..ce5eb84 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1607,8 +1607,7 @@
mWmService.mAccessibilityController;
final int winTransit = TRANSIT_EXIT;
mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
- //TODO (multidisplay): Magnification is supported only for the default
- if (accessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
+ if (accessibilityController != null) {
accessibilityController.onWindowTransitionLocked(this, winTransit);
}
}
@@ -1625,8 +1624,7 @@
if (isVisibleNow()) {
mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
- //TODO (multidisplay): Magnification is supported only for the default
- if (mWmService.mAccessibilityController != null && isDefaultDisplay()) {
+ if (mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT);
}
changed = true;
@@ -1915,9 +1913,7 @@
setDisplayLayoutNeeded();
mWmService.requestTraversal();
}
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (mWmService.mAccessibilityController != null
- && displayId == DEFAULT_DISPLAY) {
+ if (mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index fb5c556..6b4d6d2 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -1308,9 +1307,7 @@
transit = WindowManagerPolicy.TRANSIT_SHOW;
}
applyAnimationLocked(transit, true);
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (mService.mAccessibilityController != null
- && mWin.getDisplayId() == DEFAULT_DISPLAY) {
+ if (mService.mAccessibilityController != null) {
mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
index feffeef..773b877 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -20,7 +20,9 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -36,19 +38,15 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.Handler;
import android.os.Looper;
-import android.os.Message;
import android.view.MagnificationSpec;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.R;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
@@ -81,48 +79,36 @@
static final Region OTHER_REGION = new Region(OTHER_MAGNIFICATION_BOUNDS);
static final int SERVICE_ID_1 = 1;
static final int SERVICE_ID_2 = 2;
+ static final int DISPLAY_0 = 0;
+ static final int DISPLAY_1 = 1;
+ static final int DISPLAY_COUNT = 2;
+ static final int INVALID_DISPLAY = 2;
+ final MagnificationController.ControllerContext mMockControllerCtx =
+ mock(MagnificationController.ControllerContext.class);
final Context mMockContext = mock(Context.class);
final AccessibilityManagerService mMockAms = mock(AccessibilityManagerService.class);
final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
- final MessageCapturingHandler mMessageCapturingHandler =
- new MessageCapturingHandler(null);
+ final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
- final ValueAnimator mMockValueAnimator = mock(ValueAnimator.class);
- MagnificationController.SettingsBridge mMockSettingsBridge;
+ ValueAnimator mMockValueAnimator;
+ ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
MagnificationController mMagnificationController;
- ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
@Before
public void setUp() {
Looper looper = InstrumentationRegistry.getContext().getMainLooper();
// Pretending ID of the Thread associated with looper as main thread ID in controller
when(mMockContext.getMainLooper()).thenReturn(looper);
- Resources mockResources = mock(Resources.class);
- when(mMockContext.getResources()).thenReturn(mockResources);
- when(mockResources.getInteger(R.integer.config_longAnimTime))
- .thenReturn(1000);
- mMockSettingsBridge = mock(MagnificationController.SettingsBridge.class);
- mMagnificationController = new MagnificationController(mMockContext, mMockAms, new Object(),
- mMessageCapturingHandler, mMockWindowManager, mMockValueAnimator,
- mMockSettingsBridge);
+ when(mMockControllerCtx.getContext()).thenReturn(mMockContext);
+ when(mMockControllerCtx.getAms()).thenReturn(mMockAms);
+ when(mMockControllerCtx.getWindowManager()).thenReturn(mMockWindowManager);
+ when(mMockControllerCtx.getHandler()).thenReturn(mMessageCapturingHandler);
+ when(mMockControllerCtx.getAnimationDuration()).thenReturn(1000L);
+ initMockWindowManager();
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
- Object[] args = invocationOnMock.getArguments();
- Region regionArg = (Region) args[0];
- regionArg.set(INITIAL_MAGNIFICATION_REGION);
- return null;
- }
- }).when(mMockWindowManager).getMagnificationRegion((Region) anyObject());
-
- ArgumentCaptor<ValueAnimator.AnimatorUpdateListener> listenerArgumentCaptor =
- ArgumentCaptor.forClass(ValueAnimator.AnimatorUpdateListener.class);
- verify(mMockValueAnimator).addUpdateListener(listenerArgumentCaptor.capture());
- mTargetAnimationListener = listenerArgumentCaptor.getValue();
- Mockito.reset(mMockValueAnimator); // Ignore other initialization
+ mMagnificationController = new MagnificationController(mMockControllerCtx, new Object());
}
@After
@@ -133,88 +119,132 @@
@Test
public void testRegister_WindowManagerAndContextRegisterListeners() {
- mMagnificationController.register();
+ register(DISPLAY_0);
+ register(DISPLAY_1);
+ register(INVALID_DISPLAY);
verify(mMockContext).registerReceiver(
(BroadcastReceiver) anyObject(), (IntentFilter) anyObject());
- verify(mMockWindowManager).setMagnificationCallbacks((MagnificationCallbacks) anyObject());
- assertTrue(mMagnificationController.isRegisteredLocked());
+ verify(mMockWindowManager).setMagnificationCallbacks(
+ eq(DISPLAY_0), (MagnificationCallbacks) anyObject());
+ verify(mMockWindowManager).setMagnificationCallbacks(
+ eq(DISPLAY_1), (MagnificationCallbacks) anyObject());
+ verify(mMockWindowManager).setMagnificationCallbacks(
+ eq(INVALID_DISPLAY), (MagnificationCallbacks) anyObject());
+ assertTrue(mMagnificationController.isRegistered(DISPLAY_0));
+ assertTrue(mMagnificationController.isRegistered(DISPLAY_1));
+ assertFalse(mMagnificationController.isRegistered(INVALID_DISPLAY));
}
@Test
public void testRegister_WindowManagerAndContextUnregisterListeners() {
- mMagnificationController.register();
- mMagnificationController.unregister();
-
+ register(DISPLAY_0);
+ register(DISPLAY_1);
+ mMagnificationController.unregister(DISPLAY_0);
+ verify(mMockContext, times(0)).unregisterReceiver((BroadcastReceiver) anyObject());
+ mMagnificationController.unregister(DISPLAY_1);
verify(mMockContext).unregisterReceiver((BroadcastReceiver) anyObject());
- verify(mMockWindowManager).setMagnificationCallbacks(null);
- assertFalse(mMagnificationController.isRegisteredLocked());
+ verify(mMockWindowManager).setMagnificationCallbacks(eq(DISPLAY_0), eq(null));
+ verify(mMockWindowManager).setMagnificationCallbacks(eq(DISPLAY_1), eq(null));
+ assertFalse(mMagnificationController.isRegistered(DISPLAY_0));
+ assertFalse(mMagnificationController.isRegistered(DISPLAY_1));
}
@Test
public void testInitialState_noMagnificationAndMagnificationRegionReadFromWindowManager() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ initialState_noMagnificationAndMagnificationRegionReadFromWindowManager(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void initialState_noMagnificationAndMagnificationRegionReadFromWindowManager(
+ int displayId) {
+ register(displayId);
MagnificationSpec expectedInitialSpec = getMagnificationSpec(1.0f, 0.0f, 0.0f);
Region initialMagRegion = new Region();
Rect initialBounds = new Rect();
- assertEquals(expectedInitialSpec, getCurrentMagnificationSpec());
- mMagnificationController.getMagnificationRegion(initialMagRegion);
- mMagnificationController.getMagnificationBounds(initialBounds);
+ assertEquals(expectedInitialSpec, getCurrentMagnificationSpec(displayId));
+ mMagnificationController.getMagnificationRegion(displayId, initialMagRegion);
+ mMagnificationController.getMagnificationBounds(displayId, initialBounds);
assertEquals(INITIAL_MAGNIFICATION_REGION, initialMagRegion);
assertEquals(INITIAL_MAGNIFICATION_BOUNDS, initialBounds);
assertEquals(INITIAL_MAGNIFICATION_BOUNDS.centerX(),
- mMagnificationController.getCenterX(), 0.0f);
+ mMagnificationController.getCenterX(displayId), 0.0f);
assertEquals(INITIAL_MAGNIFICATION_BOUNDS.centerY(),
- mMagnificationController.getCenterY(), 0.0f);
+ mMagnificationController.getCenterY(displayId), 0.0f);
}
@Test
public void testNotRegistered_publicMethodsShouldBeBenign() {
- assertFalse(mMagnificationController.isMagnifying());
- assertFalse(mMagnificationController.magnificationRegionContains(100, 100));
- assertFalse(mMagnificationController.reset(true));
- assertFalse(mMagnificationController.setScale(2, 100, 100, true, 0));
- assertFalse(mMagnificationController.setCenter(100, 100, false, 1));
- assertFalse(mMagnificationController.setScaleAndCenter(1.5f, 100, 100, false, 2));
- assertTrue(mMagnificationController.getIdOfLastServiceToMagnify() < 0);
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ notRegistered_publicMethodsShouldBeBenign(i);
+ resetMockWindowManager();
+ }
+ }
- mMagnificationController.getMagnificationRegion(new Region());
- mMagnificationController.getMagnificationBounds(new Rect());
- mMagnificationController.getScale();
- mMagnificationController.getOffsetX();
- mMagnificationController.getOffsetY();
- mMagnificationController.getCenterX();
- mMagnificationController.getCenterY();
- mMagnificationController.offsetMagnifiedRegion(50, 50, 1);
- mMagnificationController.unregister();
+ private void notRegistered_publicMethodsShouldBeBenign(int displayId) {
+ assertFalse(mMagnificationController.isMagnifying(displayId));
+ assertFalse(mMagnificationController.magnificationRegionContains(displayId, 100, 100));
+ assertFalse(mMagnificationController.reset(displayId, true));
+ assertFalse(mMagnificationController.setScale(displayId, 2, 100, 100, true, 0));
+ assertFalse(mMagnificationController.setCenter(displayId, 100, 100, false, 1));
+ assertFalse(mMagnificationController.setScaleAndCenter(displayId,
+ 1.5f, 100, 100, false, 2));
+ assertTrue(mMagnificationController.getIdOfLastServiceToMagnify(displayId) < 0);
+
+ mMagnificationController.getMagnificationRegion(displayId, new Region());
+ mMagnificationController.getMagnificationBounds(displayId, new Rect());
+ mMagnificationController.getScale(displayId);
+ mMagnificationController.getOffsetX(displayId);
+ mMagnificationController.getOffsetY(displayId);
+ mMagnificationController.getCenterX(displayId);
+ mMagnificationController.getCenterY(displayId);
+ mMagnificationController.offsetMagnifiedRegion(displayId, 50, 50, 1);
+ mMagnificationController.unregister(displayId);
}
@Test
public void testSetScale_noAnimation_shouldGoStraightToWindowManagerAndUpdateState() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setScale_noAnimation_shouldGoStraightToWindowManagerAndUpdateState(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void setScale_noAnimation_shouldGoStraightToWindowManagerAndUpdateState(int displayId) {
+ register(displayId);
final float scale = 2.0f;
final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
final PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, center, scale);
assertTrue(mMagnificationController
- .setScale(scale, center.x, center.y, false, SERVICE_ID_1));
+ .setScale(displayId, scale, center.x, center.y, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
final MagnificationSpec expectedSpec = getMagnificationSpec(scale, offsets);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
- assertThat(getCurrentMagnificationSpec(), closeTo(expectedSpec));
- assertEquals(center.x, mMagnificationController.getCenterX(), 0.0);
- assertEquals(center.y, mMagnificationController.getCenterY(), 0.0);
+ verify(mMockWindowManager).setMagnificationSpec(
+ eq(displayId), argThat(closeTo(expectedSpec)));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(expectedSpec));
+ assertEquals(center.x, mMagnificationController.getCenterX(displayId), 0.0);
+ assertEquals(center.y, mMagnificationController.getCenterY(displayId), 0.0);
verify(mMockValueAnimator, times(0)).start();
}
@Test
public void testSetScale_withPivotAndAnimation_stateChangesAndAnimationHappens() {
- mMagnificationController.register();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setScale_withPivotAndAnimation_stateChangesAndAnimationHappens(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void setScale_withPivotAndAnimation_stateChangesAndAnimationHappens(int displayId) {
+ register(displayId);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
float scale = 2.0f;
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mMagnificationController
- .setScale(scale, pivotPoint.x, pivotPoint.y, true, SERVICE_ID_1));
+ .setScale(displayId, scale, pivotPoint.x, pivotPoint.y, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
// New center should be halfway between original center and pivot
@@ -223,467 +253,645 @@
PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
- assertThat(getCurrentMagnificationSpec(), closeTo(endSpec));
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.5);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.5);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(endSpec));
verify(mMockValueAnimator).start();
// Initial value
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(startSpec);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), eq(startSpec));
// Intermediate point
Mockito.reset(mMockWindowManager);
float fraction = 0.5f;
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
argThat(closeTo(getInterpolatedMagSpec(startSpec, endSpec, fraction))));
// Final value
Mockito.reset(mMockWindowManager);
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
}
@Test
public void testSetCenter_whileMagnifying_noAnimation_centerMoves() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setCenter_whileMagnifying_noAnimation_centerMoves(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void setCenter_whileMagnifying_noAnimation_centerMoves(int displayId) {
+ register(displayId);
// First zoom in
float scale = 2.0f;
- assertTrue(mMagnificationController.setScale(scale,
+ assertTrue(mMagnificationController.setScale(displayId, scale,
INITIAL_MAGNIFICATION_BOUNDS.centerX(), INITIAL_MAGNIFICATION_BOUNDS.centerY(),
false, SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mMagnificationController
- .setCenter(newCenter.x, newCenter.y, false, SERVICE_ID_1));
+ .setCenter(displayId, newCenter.x, newCenter.y, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
MagnificationSpec expectedSpec = getMagnificationSpec(scale, expectedOffsets);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.0);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.0);
+ verify(mMockWindowManager).setMagnificationSpec(
+ eq(displayId), argThat(closeTo(expectedSpec)));
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.0);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.0);
verify(mMockValueAnimator, times(0)).start();
}
@Test
public void testSetScaleAndCenter_animated_stateChangesAndAnimationHappens() {
- mMagnificationController.register();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setScaleAndCenter_animated_stateChangesAndAnimationHappens(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void setScaleAndCenter_animated_stateChangesAndAnimationHappens(int displayId) {
+ register(displayId);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
float scale = 2.5f;
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
- assertTrue(mMagnificationController.setScaleAndCenter(scale, newCenter.x, newCenter.y,
- true, SERVICE_ID_1));
+ assertTrue(mMagnificationController.setScaleAndCenter(displayId, scale, newCenter.x,
+ newCenter.y, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
- assertThat(getCurrentMagnificationSpec(), closeTo(endSpec));
- verify(mMockAms).notifyMagnificationChanged(
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.5);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.5);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(endSpec));
+ verify(mMockAms).notifyMagnificationChanged(displayId,
INITIAL_MAGNIFICATION_REGION, scale, newCenter.x, newCenter.y);
verify(mMockValueAnimator).start();
// Initial value
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(startSpec);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), eq(startSpec));
// Intermediate point
Mockito.reset(mMockWindowManager);
float fraction = 0.33f;
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
argThat(closeTo(getInterpolatedMagSpec(startSpec, endSpec, fraction))));
// Final value
Mockito.reset(mMockWindowManager);
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
}
@Test
public void testSetScaleAndCenter_scaleOutOfBounds_cappedAtLimits() {
- mMagnificationController.register();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setScaleAndCenter_scaleOutOfBounds_cappedAtLimits(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void setScaleAndCenter_scaleOutOfBounds_cappedAtLimits(int displayId) {
+ register(displayId);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter,
MagnificationController.MAX_SCALE);
MagnificationSpec endSpec = getMagnificationSpec(
MagnificationController.MAX_SCALE, offsets);
- assertTrue(mMagnificationController.setScaleAndCenter(
+ assertTrue(mMagnificationController.setScaleAndCenter(displayId,
MagnificationController.MAX_SCALE + 1.0f,
newCenter.x, newCenter.y, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.5);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.5);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
Mockito.reset(mMockWindowManager);
// Verify that we can't zoom below 1x
- assertTrue(mMagnificationController.setScaleAndCenter(0.5f,
+ assertTrue(mMagnificationController.setScaleAndCenter(displayId, 0.5f,
INITIAL_MAGNIFICATION_BOUNDS_CENTER.x, INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.x,
- mMagnificationController.getCenterX(), 0.5);
+ mMagnificationController.getCenterX(displayId), 0.5);
assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
- mMagnificationController.getCenterY(), 0.5);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(startSpec)));
+ mMagnificationController.getCenterY(displayId), 0.5);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(startSpec)));
}
@Test
public void testSetScaleAndCenter_centerOutOfBounds_cappedAtLimits() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setScaleAndCenter_centerOutOfBounds_cappedAtLimits(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void setScaleAndCenter_centerOutOfBounds_cappedAtLimits(int displayId) {
+ register(displayId);
float scale = 2.0f;
// Off the edge to the top and left
- assertTrue(mMagnificationController.setScaleAndCenter(
+ assertTrue(mMagnificationController.setScaleAndCenter(displayId,
scale, -100f, -200f, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
PointF newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
- verify(mMockWindowManager).setMagnificationSpec(
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.5);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.5);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
argThat(closeTo(getMagnificationSpec(scale, newOffsets))));
Mockito.reset(mMockWindowManager);
// Off the edge to the bottom and right
- assertTrue(mMagnificationController.setScaleAndCenter(scale,
+ assertTrue(mMagnificationController.setScaleAndCenter(displayId, scale,
INITIAL_MAGNIFICATION_BOUNDS.right + 1, INITIAL_MAGNIFICATION_BOUNDS.bottom + 1,
false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
- verify(mMockWindowManager).setMagnificationSpec(
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.5);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.5);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
argThat(closeTo(getMagnificationSpec(scale, newOffsets))));
}
@Test
public void testMagnificationRegionChanged_serviceNotified() {
- mMagnificationController.register();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ magnificationRegionChanged_serviceNotified(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void magnificationRegionChanged_serviceNotified(int displayId) {
+ register(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
callbacks.onMagnificationRegionChanged(OTHER_REGION);
mMessageCapturingHandler.sendAllMessages();
- verify(mMockAms).notifyMagnificationChanged(OTHER_REGION, 1.0f,
+ verify(mMockAms).notifyMagnificationChanged(displayId, OTHER_REGION, 1.0f,
OTHER_MAGNIFICATION_BOUNDS.centerX(), OTHER_MAGNIFICATION_BOUNDS.centerY());
}
@Test
public void testOffsetMagnifiedRegion_whileMagnifying_offsetsMove() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ offsetMagnifiedRegion_whileMagnifying_offsetsMove(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void offsetMagnifiedRegion_whileMagnifying_offsetsMove(int displayId) {
+ register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
PointF startOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, startCenter, scale);
// First zoom in
assertTrue(mMagnificationController
- .setScaleAndCenter(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1));
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
Mockito.reset(mMockWindowManager);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
PointF newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
- mMagnificationController.offsetMagnifiedRegion(
- startOffsets.x - newOffsets.x, startOffsets.y - newOffsets.y, SERVICE_ID_1);
+ mMagnificationController.offsetMagnifiedRegion(displayId,
+ startOffsets.x - newOffsets.x, startOffsets.y - newOffsets.y,
+ SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec expectedSpec = getMagnificationSpec(scale, newOffsets);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
- assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.0);
- assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.0);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(expectedSpec)));
+ assertEquals(newCenter.x, mMagnificationController.getCenterX(displayId), 0.0);
+ assertEquals(newCenter.y, mMagnificationController.getCenterY(displayId), 0.0);
verify(mMockValueAnimator, times(0)).start();
}
@Test
public void testOffsetMagnifiedRegion_whileNotMagnifying_hasNoEffect() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ offsetMagnifiedRegion_whileNotMagnifying_hasNoEffect(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void offsetMagnifiedRegion_whileNotMagnifying_hasNoEffect(int displayId) {
+ register(displayId);
Mockito.reset(mMockWindowManager);
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
- mMagnificationController.offsetMagnifiedRegion(10, 10, SERVICE_ID_1);
- assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
- mMagnificationController.offsetMagnifiedRegion(-10, -10, SERVICE_ID_1);
- assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
+ mMagnificationController.offsetMagnifiedRegion(displayId, 10, 10, SERVICE_ID_1);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
+ mMagnificationController.offsetMagnifiedRegion(displayId, -10, -10, SERVICE_ID_1);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
verifyNoMoreInteractions(mMockWindowManager);
}
@Test
public void testOffsetMagnifiedRegion_whileMagnifyingButAtEdge_hasNoEffect() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ offsetMagnifiedRegion_whileMagnifyingButAtEdge_hasNoEffect(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void offsetMagnifiedRegion_whileMagnifyingButAtEdge_hasNoEffect(int displayId) {
+ register(displayId);
float scale = 2.0f;
// Upper left edges
PointF ulCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
assertTrue(mMagnificationController
- .setScaleAndCenter(scale, ulCenter.x, ulCenter.y, false, SERVICE_ID_1));
+ .setScaleAndCenter(displayId, scale, ulCenter.x, ulCenter.y, false,
+ SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
- MagnificationSpec ulSpec = getCurrentMagnificationSpec();
- mMagnificationController.offsetMagnifiedRegion(-10, -10, SERVICE_ID_1);
- assertThat(getCurrentMagnificationSpec(), closeTo(ulSpec));
+ MagnificationSpec ulSpec = getCurrentMagnificationSpec(displayId);
+ mMagnificationController.offsetMagnifiedRegion(displayId, -10, -10,
+ SERVICE_ID_1);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(ulSpec));
verifyNoMoreInteractions(mMockWindowManager);
// Lower right edges
PointF lrCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mMagnificationController
- .setScaleAndCenter(scale, lrCenter.x, lrCenter.y, false, SERVICE_ID_1));
+ .setScaleAndCenter(displayId, scale, lrCenter.x, lrCenter.y, false,
+ SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
- MagnificationSpec lrSpec = getCurrentMagnificationSpec();
- mMagnificationController.offsetMagnifiedRegion(10, 10, SERVICE_ID_1);
- assertThat(getCurrentMagnificationSpec(), closeTo(lrSpec));
+ MagnificationSpec lrSpec = getCurrentMagnificationSpec(displayId);
+ mMagnificationController.offsetMagnifiedRegion(displayId, 10, 10,
+ SERVICE_ID_1);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(lrSpec));
verifyNoMoreInteractions(mMockWindowManager);
}
@Test
public void testGetIdOfLastServiceToChange_returnsCorrectValue() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ getIdOfLastServiceToChange_returnsCorrectValue(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void getIdOfLastServiceToChange_returnsCorrectValue(int displayId) {
+ register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
assertTrue(mMagnificationController
- .setScale(2.0f, startCenter.x, startCenter.y, false, SERVICE_ID_1));
- assertEquals(SERVICE_ID_1, mMagnificationController.getIdOfLastServiceToMagnify());
+ .setScale(displayId, 2.0f, startCenter.x, startCenter.y, false,
+ SERVICE_ID_1));
+ assertEquals(SERVICE_ID_1, mMagnificationController.getIdOfLastServiceToMagnify(displayId));
assertTrue(mMagnificationController
- .setScale(1.5f, startCenter.x, startCenter.y, false, SERVICE_ID_2));
- assertEquals(SERVICE_ID_2, mMagnificationController.getIdOfLastServiceToMagnify());
+ .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
+ SERVICE_ID_2));
+ assertEquals(SERVICE_ID_2, mMagnificationController.getIdOfLastServiceToMagnify(displayId));
}
@Test
public void testResetIfNeeded_resetsOnlyIfLastMagnifyingServiceIsDisabled() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ resetIfNeeded_resetsOnlyIfLastMagnifyingServiceIsDisabled(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void resetIfNeeded_resetsOnlyIfLastMagnifyingServiceIsDisabled(int displayId) {
+ register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
mMagnificationController
- .setScale(2.0f, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+ .setScale(displayId, 2.0f, startCenter.x, startCenter.y, false,
+ SERVICE_ID_1);
mMagnificationController
- .setScale(1.5f, startCenter.x, startCenter.y, false, SERVICE_ID_2);
- assertFalse(mMagnificationController.resetIfNeeded(SERVICE_ID_1));
- assertTrue(mMagnificationController.isMagnifying());
- assertTrue(mMagnificationController.resetIfNeeded(SERVICE_ID_2));
- assertFalse(mMagnificationController.isMagnifying());
+ .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
+ SERVICE_ID_2);
+ assertFalse(mMagnificationController.resetIfNeeded(displayId, SERVICE_ID_1));
+ assertTrue(mMagnificationController.isMagnifying(displayId));
+ assertTrue(mMagnificationController.resetIfNeeded(displayId, SERVICE_ID_2));
+ assertFalse(mMagnificationController.isMagnifying(displayId));
}
@Test
public void testSetUserId_resetsOnlyIfIdChanges() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ testSetUserId_resetsOnlyIfIdChanges(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void testSetUserId_resetsOnlyIfIdChanges(int displayId) {
final int userId1 = 1;
final int userId2 = 2;
- mMagnificationController.register();
+ register(displayId);
mMagnificationController.setUserId(userId1);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
- mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+ mMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y, false,
+ SERVICE_ID_1);
mMagnificationController.setUserId(userId1);
- assertTrue(mMagnificationController.isMagnifying());
+ assertTrue(mMagnificationController.isMagnifying(displayId));
mMagnificationController.setUserId(userId2);
- assertFalse(mMagnificationController.isMagnifying());
+ assertFalse(mMagnificationController.isMagnifying(displayId));
}
@Test
public void testResetIfNeeded_doesWhatItSays() {
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ testResetIfNeeded_doesWhatItSays(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void testResetIfNeeded_doesWhatItSays(int displayId) {
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
reset(mMockAms);
- assertTrue(mMagnificationController.resetIfNeeded(false));
- verify(mMockAms).notifyMagnificationChanged(
+ assertTrue(mMagnificationController.resetIfNeeded(displayId, false));
+ verify(mMockAms).notifyMagnificationChanged(eq(displayId),
eq(INITIAL_MAGNIFICATION_REGION), eq(1.0f), anyFloat(), anyFloat());
- assertFalse(mMagnificationController.isMagnifying());
- assertFalse(mMagnificationController.resetIfNeeded(false));
+ assertFalse(mMagnificationController.isMagnifying(displayId));
+ assertFalse(mMagnificationController.resetIfNeeded(displayId, false));
}
@Test
public void testTurnScreenOff_resetsMagnification() {
- mMagnificationController.register();
+ register(DISPLAY_0);
+ register(DISPLAY_1);
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mMockContext).registerReceiver(
broadcastReceiverCaptor.capture(), (IntentFilter) anyObject());
BroadcastReceiver br = broadcastReceiverCaptor.getValue();
- zoomIn2xToMiddle();
+ zoomIn2xToMiddle(DISPLAY_0);
+ zoomIn2xToMiddle(DISPLAY_1);
mMessageCapturingHandler.sendAllMessages();
br.onReceive(mMockContext, null);
mMessageCapturingHandler.sendAllMessages();
- assertFalse(mMagnificationController.isMagnifying());
+ assertFalse(mMagnificationController.isMagnifying(DISPLAY_0));
+ assertFalse(mMagnificationController.isMagnifying(DISPLAY_1));
}
@Test
public void testUserContextChange_resetsMagnification() {
- mMagnificationController.register();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ contextChange_resetsMagnification(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void contextChange_resetsMagnification(int displayId) {
+ register(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
callbacks.onUserContextChanged();
mMessageCapturingHandler.sendAllMessages();
- assertFalse(mMagnificationController.isMagnifying());
+ assertFalse(mMagnificationController.isMagnifying(displayId));
}
@Test
public void testRotation_resetsMagnification() {
- mMagnificationController.register();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ rotation_resetsMagnification(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void rotation_resetsMagnification(int displayId) {
+ register(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- assertTrue(mMagnificationController.isMagnifying());
+ assertTrue(mMagnificationController.isMagnifying(displayId));
callbacks.onRotationChanged(0);
mMessageCapturingHandler.sendAllMessages();
- assertFalse(mMagnificationController.isMagnifying());
+ assertFalse(mMagnificationController.isMagnifying(displayId));
}
@Test
public void testBoundsChange_whileMagnifyingWithCompatibleSpec_noSpecChange() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ boundsChange_whileMagnifyingWithCompatibleSpec_noSpecChange(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void boundsChange_whileMagnifyingWithCompatibleSpec_noSpecChange(int displayId) {
// Going from a small region to a large one leads to no issues
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
callbacks.onMagnificationRegionChanged(OTHER_REGION_COMPAT);
mMessageCapturingHandler.sendAllMessages();
- assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
verifyNoMoreInteractions(mMockWindowManager);
}
@Test
public void testBoundsChange_whileZoomingWithCompatibleSpec_noSpecChange() {
- mMagnificationController.register();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ boundsChange_whileZoomingWithCompatibleSpec_noSpecChange(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void boundsChange_whileZoomingWithCompatibleSpec_noSpecChange(int displayId) {
+ register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
// setting animate parameter to true is differ from zoomIn2xToMiddle()
- mMagnificationController.setScale(scale, startCenter.x, startCenter.y, true, SERVICE_ID_1);
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ mMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y, true,
+ SERVICE_ID_1);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
callbacks.onMagnificationRegionChanged(OTHER_REGION_COMPAT);
mMessageCapturingHandler.sendAllMessages();
- assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
verifyNoMoreInteractions(mMockWindowManager);
}
@Test
public void testBoundsChange_whileMagnifyingWithIncompatibleSpec_offsetsConstrained() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ boundsChange_whileMagnifyingWithIncompatibleSpec_offsetsConstrained(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void boundsChange_whileMagnifyingWithIncompatibleSpec_offsetsConstrained(
+ int displayId) {
// In a large region, pan to the farthest point possible
- mMagnificationController.register();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ register(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
callbacks.onMagnificationRegionChanged(OTHER_REGION);
mMessageCapturingHandler.sendAllMessages();
PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
float scale = 2.0f;
- mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+ mMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y, false,
+ SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(startSpec)));
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(startSpec)));
Mockito.reset(mMockWindowManager);
callbacks.onMagnificationRegionChanged(INITIAL_MAGNIFICATION_REGION);
mMessageCapturingHandler.sendAllMessages();
- MagnificationSpec endSpec = getCurrentMagnificationSpec();
+ MagnificationSpec endSpec = getCurrentMagnificationSpec(displayId);
assertThat(endSpec, CoreMatchers.not(closeTo(startSpec)));
PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS,
INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER, scale);
assertThat(endSpec, closeTo(getMagnificationSpec(scale, expectedOffsets)));
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
}
@Test
public void testBoundsChange_whileZoomingWithIncompatibleSpec_jumpsToCompatibleSpec() {
- mMagnificationController.register();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ boundsChange_whileZoomingWithIncompatibleSpec_jumpsToCompatibleSpec(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void boundsChange_whileZoomingWithIncompatibleSpec_jumpsToCompatibleSpec(
+ int displayId) {
+ register(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
callbacks.onMagnificationRegionChanged(OTHER_REGION);
mMessageCapturingHandler.sendAllMessages();
PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
float scale = 2.0f;
- mMagnificationController.setScale(scale, startCenter.x, startCenter.y, true, SERVICE_ID_1);
+ mMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y, true,
+ SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
when(mMockValueAnimator.isRunning()).thenReturn(true);
callbacks.onMagnificationRegionChanged(INITIAL_MAGNIFICATION_REGION);
mMessageCapturingHandler.sendAllMessages();
verify(mMockValueAnimator).cancel();
- MagnificationSpec endSpec = getCurrentMagnificationSpec();
+ MagnificationSpec endSpec = getCurrentMagnificationSpec(displayId);
assertThat(endSpec, CoreMatchers.not(closeTo(startSpec)));
PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS,
INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER, scale);
assertThat(endSpec, closeTo(getMagnificationSpec(scale, expectedOffsets)));
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
}
@Test
public void testRequestRectOnScreen_rectAlreadyOnScreen_doesNothing() {
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ requestRectOnScreen_rectAlreadyOnScreen_doesNothing(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void requestRectOnScreen_rectAlreadyOnScreen_doesNothing(int displayId) {
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
int centerX = (int) INITIAL_MAGNIFICATION_BOUNDS_CENTER.x;
int centerY = (int) INITIAL_MAGNIFICATION_BOUNDS_CENTER.y;
callbacks.onRectangleOnScreenRequested(centerX - 1, centerY - 1, centerX + 1, centerY - 1);
mMessageCapturingHandler.sendAllMessages();
- assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
verifyNoMoreInteractions(mMockWindowManager);
}
@Test
public void testRequestRectOnScreen_rectCanFitOnScreen_pansToGetRectOnScreen() {
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ requestRectOnScreen_rectCanFitOnScreen_pansToGetRectOnScreen(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void requestRectOnScreen_rectCanFitOnScreen_pansToGetRectOnScreen(int displayId) {
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
callbacks.onRectangleOnScreenRequested(0, 0, 1, 1);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec expectedEndSpec = getMagnificationSpec(2.0f, 0, 0);
- assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(expectedEndSpec));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(expectedEndSpec)));
}
@Test
public void testRequestRectOnScreen_garbageInput_doesNothing() {
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ requestRectOnScreen_garbageInput_doesNothing(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void requestRectOnScreen_garbageInput_doesNothing(int displayId) {
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
callbacks.onRectangleOnScreenRequested(0, 0, -50, -50);
mMessageCapturingHandler.sendAllMessages();
- assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
verifyNoMoreInteractions(mMockWindowManager);
}
@Test
public void testRequestRectOnScreen_rectTooWide_pansToGetStartOnScreenBasedOnLocale() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ requestRectOnScreen_rectTooWide_pansToGetStartOnScreenBasedOnLocale(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void requestRectOnScreen_rectTooWide_pansToGetStartOnScreenBasedOnLocale(
+ int displayId) {
Locale.setDefault(new Locale("en", "us"));
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
Mockito.reset(mMockWindowManager);
Rect wideRect = new Rect(0, 50, 100, 51);
callbacks.onRectangleOnScreenRequested(
wideRect.left, wideRect.top, wideRect.right, wideRect.bottom);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec expectedEndSpec = getMagnificationSpec(2.0f, 0, startSpec.offsetY);
- assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(expectedEndSpec));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(expectedEndSpec)));
Mockito.reset(mMockWindowManager);
// Repeat with RTL
@@ -692,50 +900,66 @@
wideRect.left, wideRect.top, wideRect.right, wideRect.bottom);
mMessageCapturingHandler.sendAllMessages();
expectedEndSpec = getMagnificationSpec(2.0f, -100, startSpec.offsetY);
- assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(expectedEndSpec));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(expectedEndSpec)));
}
@Test
public void testRequestRectOnScreen_rectTooTall_pansMinimumToGetTopOnScreen() {
- mMagnificationController.register();
- zoomIn2xToMiddle();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ requestRectOnScreen_rectTooTall_pansMinimumToGetTopOnScreen(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void requestRectOnScreen_rectTooTall_pansMinimumToGetTopOnScreen(int displayId) {
+ register(displayId);
+ zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- MagnificationCallbacks callbacks = getMagnificationCallbacks();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
Mockito.reset(mMockWindowManager);
Rect tallRect = new Rect(50, 0, 51, 100);
callbacks.onRectangleOnScreenRequested(
tallRect.left, tallRect.top, tallRect.right, tallRect.bottom);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec expectedEndSpec = getMagnificationSpec(2.0f, startSpec.offsetX, 0);
- assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(expectedEndSpec));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(expectedEndSpec)));
}
@Test
public void testChangeMagnification_duringAnimation_animatesToNewValue() {
- mMagnificationController.register();
- MagnificationSpec startSpec = getCurrentMagnificationSpec();
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ changeMagnification_duringAnimation_animatesToNewValue(i);
+ resetMockWindowManager();
+ }
+ }
+
+ private void changeMagnification_duringAnimation_animatesToNewValue(int displayId) {
+ register(displayId);
+ MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
float scale = 2.5f;
PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
MagnificationSpec firstEndSpec = getMagnificationSpec(
scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, firstCenter, scale));
- assertTrue(mMagnificationController.setScaleAndCenter(scale, firstCenter.x, firstCenter.y,
- true, SERVICE_ID_1));
+ assertTrue(mMagnificationController.setScaleAndCenter(displayId,
+ scale, firstCenter.x, firstCenter.y, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
- assertEquals(firstCenter.x, mMagnificationController.getCenterX(), 0.5);
- assertEquals(firstCenter.y, mMagnificationController.getCenterY(), 0.5);
- assertThat(getCurrentMagnificationSpec(), closeTo(firstEndSpec));
+ assertEquals(firstCenter.x, mMagnificationController.getCenterX(displayId), 0.5);
+ assertEquals(firstCenter.y, mMagnificationController.getCenterY(displayId), 0.5);
+ assertThat(getCurrentMagnificationSpec(displayId), closeTo(firstEndSpec));
verify(mMockValueAnimator, times(1)).start();
// Initial value
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(startSpec);
- verify(mMockAms).notifyMagnificationChanged(
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId), eq(startSpec));
+ verify(mMockAms).notifyMagnificationChanged(displayId,
INITIAL_MAGNIFICATION_REGION, scale, firstCenter.x, firstCenter.y);
Mockito.reset(mMockWindowManager);
@@ -745,32 +969,34 @@
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
MagnificationSpec intermediateSpec1 =
getInterpolatedMagSpec(startSpec, firstEndSpec, fraction);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(intermediateSpec1)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(intermediateSpec1)));
Mockito.reset(mMockWindowManager);
PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
MagnificationSpec newEndSpec = getMagnificationSpec(
scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale));
- assertTrue(mMagnificationController.setCenter(
+ assertTrue(mMagnificationController.setCenter(displayId,
newCenter.x, newCenter.y, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
// Animation should have been restarted
verify(mMockValueAnimator, times(2)).start();
- verify(mMockAms).notifyMagnificationChanged(
+ verify(mMockAms).notifyMagnificationChanged(displayId,
INITIAL_MAGNIFICATION_REGION, scale, newCenter.x, newCenter.y);
// New starting point should be where we left off
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(intermediateSpec1)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(intermediateSpec1)));
Mockito.reset(mMockWindowManager);
// Second intermediate point
fraction = 0.5f;
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
argThat(closeTo(getInterpolatedMagSpec(intermediateSpec1, newEndSpec, fraction))));
Mockito.reset(mMockWindowManager);
@@ -778,21 +1004,54 @@
Mockito.reset(mMockWindowManager);
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
- verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(newEndSpec)));
+ verify(mMockWindowManager).setMagnificationSpec(eq(displayId),
+ argThat(closeTo(newEndSpec)));
}
- private void zoomIn2xToMiddle() {
+ private void initMockWindowManager() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ when(mMockWindowManager.setMagnificationCallbacks(eq(i), any())).thenReturn(true);
+ }
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+ Object[] args = invocationOnMock.getArguments();
+ Region regionArg = (Region) args[1];
+ regionArg.set(INITIAL_MAGNIFICATION_REGION);
+ return null;
+ }
+ }).when(mMockWindowManager).getMagnificationRegion(anyInt(), (Region) anyObject());
+ }
+
+ private void resetMockWindowManager() {
+ Mockito.reset(mMockWindowManager);
+ initMockWindowManager();
+ }
+
+ private void register(int displayId) {
+ mMockValueAnimator = mock(ValueAnimator.class);
+ when(mMockControllerCtx.newValueAnimator()).thenReturn(mMockValueAnimator);
+ mMagnificationController.register(displayId);
+ ArgumentCaptor<ValueAnimator.AnimatorUpdateListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(ValueAnimator.AnimatorUpdateListener.class);
+ verify(mMockValueAnimator).addUpdateListener(listenerArgumentCaptor.capture());
+ mTargetAnimationListener = listenerArgumentCaptor.getValue();
+ Mockito.reset(mMockValueAnimator); // Ignore other initialization
+ }
+
+ private void zoomIn2xToMiddle(int displayId) {
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
- mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
- assertTrue(mMagnificationController.isMagnifying());
+ mMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y, false,
+ SERVICE_ID_1);
+ assertTrue(mMagnificationController.isMagnifying(displayId));
}
- private MagnificationCallbacks getMagnificationCallbacks() {
+ private MagnificationCallbacks getMagnificationCallbacks(int displayId) {
ArgumentCaptor<MagnificationCallbacks> magnificationCallbacksCaptor =
ArgumentCaptor.forClass(MagnificationCallbacks.class);
verify(mMockWindowManager)
- .setMagnificationCallbacks(magnificationCallbacksCaptor.capture());
+ .setMagnificationCallbacks(eq(displayId), magnificationCallbacksCaptor.capture());
return magnificationCallbacksCaptor.getValue();
}
@@ -823,9 +1082,10 @@
return spec;
}
- private MagnificationSpec getCurrentMagnificationSpec() {
- return getMagnificationSpec(mMagnificationController.getScale(),
- mMagnificationController.getOffsetX(), mMagnificationController.getOffsetY());
+ private MagnificationSpec getCurrentMagnificationSpec(int displayId) {
+ return getMagnificationSpec(mMagnificationController.getScale(displayId),
+ mMagnificationController.getOffsetX(displayId),
+ mMagnificationController.getOffsetY(displayId));
}
private MagSpecMatcher closeTo(MagnificationSpec spec) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
index 032074a..5083110 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
@@ -26,16 +26,19 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.Context;
+import android.os.Handler;
import android.os.Message;
import android.util.DebugUtils;
import android.view.InputDevice;
@@ -104,14 +107,9 @@
public static final float DEFAULT_X = 301;
public static final float DEFAULT_Y = 299;
+ private static final int DISPLAY_0 = 0;
+
private Context mContext;
- final AccessibilityManagerService mMockAms = mock(AccessibilityManagerService.class);
- final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
- final MessageCapturingHandler mMessageCapturingHandler =
- new MessageCapturingHandler(null);
- final ValueAnimator mMockValueAnimator = mock(ValueAnimator.class);
- MagnificationController.SettingsBridge mMockSettingsBridge =
- mock(MagnificationController.SettingsBridge.class);
MagnificationController mMagnificationController;
private OffsettableClock mClock;
@@ -123,18 +121,26 @@
@Before
public void setUp() {
mContext = InstrumentationRegistry.getContext();
- mMagnificationController = new MagnificationController(mContext, mMockAms, new Object(),
- mMessageCapturingHandler, mMockWindowManager, mMockValueAnimator,
- mMockSettingsBridge) {
+ final MagnificationController.ControllerContext mockController =
+ mock(MagnificationController.ControllerContext.class);
+ final WindowManagerInternal mockWindowManager = mock(WindowManagerInternal.class);
+ when(mockController.getContext()).thenReturn(mContext);
+ when(mockController.getAms()).thenReturn(mock(AccessibilityManagerService.class));
+ when(mockController.getWindowManager()).thenReturn(mockWindowManager);
+ when(mockController.getHandler()).thenReturn(new Handler(mContext.getMainLooper()));
+ when(mockController.newValueAnimator()).thenReturn(new ValueAnimator());
+ when(mockController.getAnimationDuration()).thenReturn(1000L);
+ when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
+ mMagnificationController = new MagnificationController(mockController, new Object()) {
@Override
- public boolean magnificationRegionContains(float x, float y) {
+ public boolean magnificationRegionContains(int displayId, float x, float y) {
return true;
}
@Override
- void setForceShowMagnifiableBounds(boolean show) {}
+ void setForceShowMagnifiableBounds(int displayId, boolean show) {}
};
- mMagnificationController.register();
+ mMagnificationController.register(DISPLAY_0);
mClock = new OffsettableClock.Stopped();
boolean detectTripleTap = true;
@@ -144,7 +150,7 @@
@After
public void tearDown() {
- mMagnificationController.unregister();
+ mMagnificationController.unregister(DISPLAY_0);
}
@NonNull
@@ -509,7 +515,7 @@
}
private boolean isZoomed() {
- return mMgh.mMagnificationController.isMagnifying();
+ return mMgh.mMagnificationController.isMagnifying(DISPLAY_0);
}
private int tapCount() {