Merge "Implmented the aidl interface for window magnification"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user