Merge "Implmented the aidl interface for window magnification"

This commit is contained in:
Ryan Lin
2020-03-10 02:35:30 +00:00
committed by Android (Google) Code Review
4 changed files with 227 additions and 43 deletions

View File

@@ -16,13 +16,22 @@
package com.android.systemui.accessibility;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.accessibility.IWindowMagnificationConnection;
import android.view.accessibility.IWindowMagnificationConnectionCallback;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.qualifiers.Main;
@@ -33,12 +42,15 @@ import javax.inject.Singleton;
* Class to handle changes to setting window_magnification value.
*/
@Singleton
public class WindowMagnification extends SystemUI {
public class WindowMagnification extends SystemUI implements WindowMagnifierCallback {
private static final String TAG = "WindowMagnification";
private static final int CONFIG_MASK =
ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION;
private WindowMagnificationController mWindowMagnificationController;
private final Handler mHandler;
//TODO:Set it by the request from AccessibilityManager.
private WindowMagnificationConnectionImpl mWindowMagnificationConnectionImpl;
private Configuration mLastConfiguration;
@@ -78,7 +90,8 @@ public class WindowMagnification extends SystemUI {
boolean enable = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.WINDOW_MAGNIFICATION) != 0;
if (enable) {
enableMagnification();
enableMagnification(
mContext.getResources().getInteger(R.integer.magnification_default_scale));
} else {
disableMagnification();
}
@@ -87,17 +100,108 @@ public class WindowMagnification extends SystemUI {
}
}
private void enableMagnification() {
if (mWindowMagnificationController == null) {
mWindowMagnificationController = new WindowMagnificationController(mContext, null);
}
mWindowMagnificationController.createWindowMagnification();
private void enableMagnification(float scale) {
enableWindowMagnification(Display.DEFAULT_DISPLAY, scale, Float.NaN, Float.NaN);
}
private void disableMagnification() {
disableWindowMagnification(Display.DEFAULT_DISPLAY);
}
@MainThread
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY) {
//TODO: b/144080869 support multi-display.
if (mWindowMagnificationController == null) {
mWindowMagnificationController = new WindowMagnificationController(mContext, null,
this);
}
mWindowMagnificationController.enableWindowMagnification(scale, centerX, centerY);
}
@MainThread
void setScale(int displayId, float scale) {
//TODO: b/144080869 support multi-display.
if (mWindowMagnificationController != null) {
mWindowMagnificationController.setScale(scale);
}
}
@MainThread
void moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
//TODO: b/144080869 support multi-display.
if (mWindowMagnificationController != null) {
mWindowMagnificationController.moveWindowMagnifier(offsetX, offsetY);
}
}
@MainThread
void disableWindowMagnification(int displayId) {
//TODO: b/144080869 support multi-display.
if (mWindowMagnificationController != null) {
mWindowMagnificationController.deleteWindowMagnification();
}
mWindowMagnificationController = null;
}
@Override
public void onWindowMagnifierBoundsChanged(int displayId, Rect frame) {
if (mWindowMagnificationConnectionImpl != null) {
mWindowMagnificationConnectionImpl.onWindowMagnifierBoundsChanged(displayId, frame);
}
}
private static class WindowMagnificationConnectionImpl extends
IWindowMagnificationConnection.Stub {
private static final String TAG = "WindowMagnificationConnectionImpl";
private IWindowMagnificationConnectionCallback mConnectionCallback;
private final WindowMagnification mWindowMagnification;
private final Handler mHandler;
WindowMagnificationConnectionImpl(@NonNull WindowMagnification windowMagnification,
@Main Handler mainHandler) {
mWindowMagnification = windowMagnification;
mHandler = mainHandler;
}
@Override
public void enableWindowMagnification(int displayId, float scale, float centerX,
float centerY) {
mHandler.post(
() -> mWindowMagnification.enableWindowMagnification(displayId, scale, centerX,
centerY));
}
@Override
public void setScale(int displayId, float scale) {
mHandler.post(() -> mWindowMagnification.setScale(displayId, scale));
}
@Override
public void disableWindowMagnification(int displayId) {
mHandler.post(() -> mWindowMagnification.disableWindowMagnification(displayId));
}
@Override
public void moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
mHandler.post(
() -> mWindowMagnification.moveWindowMagnifier(displayId, offsetX, offsetY));
}
@Override
public void setConnectionCallback(IWindowMagnificationConnectionCallback callback) {
mConnectionCallback = callback;
}
void onWindowMagnifierBoundsChanged(int displayId, Rect frame) {
if (mConnectionCallback != null) {
try {
mConnectionCallback.onWindowMagnifierBoundsChanged(displayId, frame);
} catch (RemoteException e) {
Log.e(TAG, "Failed to inform bounds changed", e);
}
}
}
}
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.accessibility;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -29,6 +30,7 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
@@ -53,7 +55,7 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
/**
* Class to handle adding and removing a window magnification.
*/
public class WindowMagnificationController implements View.OnTouchListener, SurfaceHolder.Callback,
class WindowMagnificationController implements View.OnTouchListener, SurfaceHolder.Callback,
MirrorWindowControl.MirrorWindowDelegate {
private static final String TAG = "WindowMagnificationController";
@@ -71,6 +73,7 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
private float mScale;
private final Rect mTmpRect = new Rect();
private final Rect mMirrorViewBounds = new Rect();
// The root of the mirrored content
private SurfaceControl mMirrorSurface;
@@ -82,6 +85,7 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
private View mBottomDrag;
private final PointF mLastDrag = new PointF();
@NonNull private final WindowMagnifierCallback mWindowMagnifierCallback;
private View mMirrorView;
private SurfaceView mMirrorSurfaceView;
@@ -95,8 +99,10 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
@Nullable
private MirrorWindowControl mMirrorWindowControl;
WindowMagnificationController(Context context, MirrorWindowControl mirrorWindowControl) {
WindowMagnificationController(Context context, MirrorWindowControl mirrorWindowControl,
@NonNull WindowMagnifierCallback callback) {
mContext = context;
mWindowMagnifierCallback = callback;
Display display = mContext.getDisplay();
display.getRealSize(mDisplaySize);
mDisplayId = mContext.getDisplayId();
@@ -112,6 +118,7 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
if (mMirrorWindowControl != null) {
mMirrorWindowControl.setWindowDelegate(this);
}
setInitialStartBounds();
}
private void updateDimensions() {
@@ -123,18 +130,6 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
R.dimen.magnification_outer_border_margin);
}
/**
* Creates a magnification window if it doesn't already exist.
*/
void createWindowMagnification() {
if (mMirrorView != null) {
return;
}
setInitialStartBounds();
setMagnificationFrameBoundary();
createOverlayWindow();
}
private void createOverlayWindow() {
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,
@@ -240,9 +235,8 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
mTmpRect.set(params.x, params.y, params.x + params.width, params.y + params.height);
final RectF transformedRect = new RectF(mTmpRect);
matrix.mapRect(transformedRect);
final int offsetX = (int) transformedRect.left - mTmpRect.left;
final int offsetY = (int) transformedRect.top - mTmpRect.top;
moveMirrorWindow(offsetX, offsetY);
moveWindowMagnifier(transformedRect.left - mTmpRect.left,
transformedRect.top - mTmpRect.top);
}
/** Returns the rotation degree change of two {@link Surface.Rotation} */
@@ -289,6 +283,14 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
mMirrorView.addOnLayoutChangeListener(
(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop,
int oldRight, int oldBottom)
-> AsyncTask.execute(() -> {
mMirrorView.getBoundsOnScreen(mMirrorViewBounds);
mWindowMagnifierCallback.onWindowMagnifierBoundsChanged(mDisplayId,
mMirrorViewBounds);
}));
mWm.addView(mMirrorView, params);
SurfaceHolder holder = mMirrorSurfaceView.getHolder();
@@ -323,9 +325,10 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
private void setInitialStartBounds() {
// Sets the initial frame area for the mirror and places it in the center of the display.
int initSize = Math.min(mDisplaySize.x, mDisplaySize.y) / 2 + 2 * mMirrorSurfaceMargin;
int initX = mDisplaySize.x / 2 - initSize / 2;
int initY = mDisplaySize.y / 2 - initSize / 2;
final int initSize = Math.min(mDisplaySize.x, mDisplaySize.y) / 2
+ 2 * mMirrorSurfaceMargin;
final int initX = mDisplaySize.x / 2 - initSize / 2;
final int initY = mDisplaySize.y / 2 - initSize / 2;
mMagnificationFrame.set(initX, initY, initX + initSize, initY + initSize);
}
@@ -423,22 +426,13 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
mLastDrag.set(event.getRawX(), event.getRawY());
return true;
case MotionEvent.ACTION_MOVE:
int xDiff = (int) (event.getRawX() - mLastDrag.x);
int yDiff = (int) (event.getRawY() - mLastDrag.y);
moveMirrorWindow(xDiff, yDiff);
moveWindowMagnifier(event.getRawX() - mLastDrag.x, event.getRawY() - mLastDrag.y);
mLastDrag.set(event.getRawX(), event.getRawY());
return true;
}
return false;
}
private void moveMirrorWindow(int xOffset, int yOffset) {
if (updateMagnificationFramePosition(xOffset, yOffset)) {
modifyWindowMagnification(mTransaction);
mTransaction.apply();
}
}
/**
* Calculates the desired source bounds. This will be the area under from the center of the
* displayFrame, factoring in scale.
@@ -515,11 +509,61 @@ public class WindowMagnificationController implements View.OnTouchListener, Surf
@Override
public void move(int xOffset, int yOffset) {
moveWindowMagnifier(xOffset, yOffset);
}
/**
* Enables window magnification with specified parameters.
*
* @param scale the target scale
* @param centerX the screen-relative X coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
* @param centerY the screen-relative Y coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
*/
void enableWindowMagnification(float scale, float centerX, float centerY) {
final float offsetX = Float.isNaN(centerX) ? 0
: centerX - mMagnificationFrame.exactCenterX();
final float offsetY = Float.isNaN(centerY) ? 0
: centerY - mMagnificationFrame.exactCenterY();
mScale = scale;
setMagnificationFrameBoundary();
updateMagnificationFramePosition((int) offsetX, (int) offsetY);
if (mMirrorView == null) {
createOverlayWindow();
} else {
modifyWindowMagnification(mTransaction);
mTransaction.apply();
}
}
/**
* Sets the scale of the magnified region if it's visible.
*
* @param scale the target scale
*/
void setScale(float scale) {
if (mMirrorView == null || mScale == scale) {
return;
}
enableWindowMagnification(scale, Float.NaN, Float.NaN);
}
/**
* Moves the window magnifier with specified offset in pixels unit.
*
* @param offsetX the amount in pixels to offset the window magnifier in the X direction, in
* current screen pixels.
* @param offsetY the amount in pixels to offset the window magnifier in the Y direction, in
* current screen pixels.
*/
void moveWindowMagnifier(float offsetX, float offsetY) {
if (mMirrorSurfaceView == null) {
return;
}
mMagnificationFrame.offset(xOffset, yOffset);
modifyWindowMagnification(mTransaction);
mTransaction.apply();
if (updateMagnificationFramePosition((int) offsetX, (int) offsetY)) {
modifyWindowMagnification(mTransaction);
mTransaction.apply();
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.accessibility;
import android.graphics.Rect;
/**
* A callback to inform {@link com.android.server.accessibility.AccessibilityManagerService} about
* the UI state change or the user interaction.
*/
interface WindowMagnifierCallback {
/**
* Called when the bounds of window magnifier is changed.
* @param displayId The logical display id.
* @param bounds The bounds of window magnifier on the screen.
*/
void onWindowMagnifierBoundsChanged(int displayId, Rect bounds);
}

View File

@@ -42,6 +42,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
@Mock
MirrorWindowControl mMirrorWindowControl;
@Mock
WindowMagnifierCallback mWindowMagnifierCallback;
private WindowMagnificationController mWindowMagnificationController;
private Instrumentation mInstrumentation;
@@ -50,7 +52,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mWindowMagnificationController = new WindowMagnificationController(getContext(),
mMirrorWindowControl);
mMirrorWindowControl, mWindowMagnifierCallback);
verify(mMirrorWindowControl).setWindowDelegate(
any(MirrorWindowControl.MirrorWindowDelegate.class));
}
@@ -66,7 +68,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
@Test
public void createWindowMagnification_showControl() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.createWindowMagnification();
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN);
});
mInstrumentation.waitForIdleSync();
verify(mMirrorWindowControl).showControl(any(IBinder.class));
@@ -75,7 +78,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
@Test
public void deleteWindowMagnification_destroyControl() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.createWindowMagnification();
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN);
});
mInstrumentation.waitForIdleSync();