Merge "Waits for windowMagnification connection set when requesting enableWindowMagnification" into tm-dev

This commit is contained in:
Minche Li
2022-03-02 01:09:36 +00:00
committed by Android (Google) Code Review
9 changed files with 154 additions and 19 deletions

View File

@@ -2749,6 +2749,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
private void updateWindowMagnificationConnectionIfNeeded(AccessibilityUserState userState) {
if (!mMagnificationController.supportWindowMagnification()) {
return;
}
final boolean connect = (userState.isShortcutMagnificationEnabledLocked()
|| userState.isDisplayMagnificationEnabledLocked())
&& (userState.getMagnificationCapabilitiesLocked()

View File

@@ -17,6 +17,7 @@
package com.android.server.accessibility.magnification;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW;
import static android.content.pm.PackageManager.FEATURE_WINDOW_MAGNIFICATION;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
@@ -91,6 +92,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb
private FullScreenMagnificationController mFullScreenMagnificationController;
private WindowMagnificationManager mWindowMagnificationMgr;
private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
/** Whether the platform supports window magnification feature. */
private final boolean mSupportWindowMagnification;
@GuardedBy("mLock")
private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
@@ -129,6 +132,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb
mScaleProvider = scaleProvider;
LocalServices.getService(WindowManagerInternal.class)
.getAccessibilityController().setUiChangesForAccessibilityCallbacks(this);
mSupportWindowMagnification = context.getPackageManager().hasSystemFeature(
FEATURE_WINDOW_MAGNIFICATION);
}
@VisibleForTesting
@@ -185,6 +190,11 @@ public class MagnificationController implements WindowMagnificationManager.Callb
}
}
/** Returns {@code true} if the platform supports window magnification feature. */
public boolean supportWindowMagnification() {
return mSupportWindowMagnification;
}
/**
* Transitions to the target Magnification mode with current center of the magnification mode
* if it is available.

View File

@@ -396,6 +396,10 @@ public class MagnificationProcessor {
dumpTrackingTypingFocusEnabledState(pw, displayId, config.getMode());
}
pw.append(" SupportWindowMagnification="
+ mController.supportWindowMagnification()).println();
pw.append(" WindowMagnificationConnectionState="
+ mController.getWindowMagnificationMgr().getConnectionState()).println();
}
private int getIdOfLastServiceToMagnify(int mode, int displayId) {

View File

@@ -36,6 +36,7 @@ import android.graphics.Region;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Slog;
import android.util.SparseArray;
import android.view.MotionEvent;
@@ -87,6 +88,30 @@ public class WindowMagnificationManager implements
})
public @interface WindowPosition {}
/** Window magnification connection is connecting. */
private static final int CONNECTING = 0;
/** Window magnification connection is connected. */
private static final int CONNECTED = 1;
/** Window magnification connection is disconnecting. */
private static final int DISCONNECTING = 2;
/** Window magnification connection is disconnected. */
private static final int DISCONNECTED = 3;
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"CONNECTION_STATE"}, value = {
CONNECTING,
CONNECTED,
DISCONNECTING,
DISCONNECTED
})
private @interface ConnectionState {
}
@ConnectionState
private int mConnectionState = DISCONNECTED;
private static final int WAIT_CONNECTION_TIMEOUT_MILLIS = 100;
private final Object mLock;
private final Context mContext;
@VisibleForTesting
@@ -178,7 +203,7 @@ public class WindowMagnificationManager implements
*/
public void setConnection(@Nullable IWindowMagnificationConnection connection) {
if (DBG) {
Slog.d(TAG, "setConnection :" + connection);
Slog.d(TAG, "setConnection :" + connection + " ,mConnectionState=" + mConnectionState);
}
synchronized (mLock) {
// Reset connectionWrapper.
@@ -189,6 +214,13 @@ public class WindowMagnificationManager implements
}
mConnectionWrapper.unlinkToDeath(mConnectionCallback);
mConnectionWrapper = null;
// The connection is still connecting so it is no need to reset the
// connection state to disconnected.
// TODO b/220086369 will reset the connection immediately when requestConnection
// is called
if (mConnectionState != CONNECTING) {
setConnectionState(DISCONNECTED);
}
}
if (connection != null) {
mConnectionWrapper = new WindowMagnificationConnectionWrapper(connection, mTrace);
@@ -199,9 +231,13 @@ public class WindowMagnificationManager implements
mConnectionCallback = new ConnectionCallback();
mConnectionWrapper.linkToDeath(mConnectionCallback);
mConnectionWrapper.setConnectionCallback(mConnectionCallback);
setConnectionState(CONNECTED);
} catch (RemoteException e) {
Slog.e(TAG, "setConnection failed", e);
mConnectionWrapper = null;
setConnectionState(DISCONNECTED);
} finally {
mLock.notify();
}
}
}
@@ -229,10 +265,20 @@ public class WindowMagnificationManager implements
if (DBG) {
Slog.d(TAG, "requestConnection :" + connect);
}
if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
mTrace.logTrace(TAG + ".requestWindowMagnificationConnection",
FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "connect=" + connect);
}
synchronized (mLock) {
if (connect == isConnected()) {
if ((connect && (mConnectionState == CONNECTED || mConnectionState == CONNECTING))
|| (!connect && (mConnectionState == DISCONNECTED
|| mConnectionState == DISCONNECTING))) {
Slog.w(TAG,
"requestConnection duplicated request: connect=" + connect
+ " ,mConnectionState=" + mConnectionState);
return false;
}
if (connect) {
final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
if (!mReceiverRegistered) {
@@ -247,19 +293,42 @@ public class WindowMagnificationManager implements
}
}
}
if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
mTrace.logTrace(TAG + ".requestWindowMagnificationConnection",
FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "connect=" + connect);
if (requestConnectionInternal(connect)) {
setConnectionState(connect ? CONNECTING : DISCONNECTING);
return true;
} else {
setConnectionState(DISCONNECTED);
return false;
}
}
private boolean requestConnectionInternal(boolean connect) {
final long identity = Binder.clearCallingIdentity();
try {
final StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
service.requestWindowMagnificationConnection(connect);
if (service != null) {
return service.requestWindowMagnificationConnection(connect);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
return true;
return false;
}
/**
* Returns window magnification connection state.
*/
public int getConnectionState() {
return mConnectionState;
}
private void setConnectionState(@ConnectionState int state) {
if (DBG) {
Slog.d(TAG, "setConnectionState : state=" + state + " ,mConnectionState="
+ mConnectionState);
}
mConnectionState = state;
}
/**
@@ -849,6 +918,7 @@ public class WindowMagnificationManager implements
mConnectionWrapper.unlinkToDeath(this);
mConnectionWrapper = null;
mConnectionCallback = null;
setConnectionState(DISCONNECTED);
resetWindowMagnifiers();
}
}
@@ -1025,11 +1095,22 @@ public class WindowMagnificationManager implements
float centerY, float magnificationFrameOffsetRatioX,
float magnificationFrameOffsetRatioY,
MagnificationAnimationCallback animationCallback) {
// Wait for the connection with a timeout.
final long endMillis = SystemClock.uptimeMillis() + WAIT_CONNECTION_TIMEOUT_MILLIS;
while (mConnectionState == CONNECTING && (SystemClock.uptimeMillis() < endMillis)) {
try {
mLock.wait(endMillis - SystemClock.uptimeMillis());
} catch (InterruptedException ie) {
/* ignore */
}
}
if (mConnectionWrapper == null) {
Slog.w(TAG, "enableWindowMagnificationInternal mConnectionWrapper is null");
Slog.w(TAG,
"enableWindowMagnificationInternal mConnectionWrapper is null. "
+ "mConnectionState=" + mConnectionState);
return false;
}
return mConnectionWrapper.enableWindowMagnification(
return mConnectionWrapper.enableWindowMagnification(
displayId, scale, centerX, centerY,
magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY,
animationCallback);

View File

@@ -157,7 +157,7 @@ public interface StatusBarManagerInternal {
* @see com.android.internal.statusbar.IStatusBar#requestWindowMagnificationConnection(boolean
* request)
*/
void requestWindowMagnificationConnection(boolean request);
boolean requestWindowMagnificationConnection(boolean request);
/**
* Handles a logging command from the WM shell command.

View File

@@ -637,12 +637,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
public void requestWindowMagnificationConnection(boolean request) {
public boolean requestWindowMagnificationConnection(boolean request) {
if (mBar != null) {
try {
mBar.requestWindowMagnificationConnection(request);
return true;
} catch (RemoteException ex) { }
}
return false;
}
@Override

View File

@@ -154,6 +154,7 @@ public class AccessibilityManagerServiceTest {
mMockWindowMagnificationMgr);
when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
mMockFullScreenMagnificationController);
when(mMockMagnificationController.supportWindowMagnification()).thenReturn(true);
when(mMockWindowManagerService.getAccessibilityController()).thenReturn(
mMockA11yController);
when(mMockA11yController.isAccessibilityTracingEnabled()).thenReturn(false);

View File

@@ -41,6 +41,7 @@ import static org.mockito.Mockito.when;
import android.accessibilityservice.MagnificationConfig;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
@@ -100,6 +101,8 @@ public class MagnificationControllerTest {
@Mock
private Context mContext;
@Mock
PackageManager mPackageManager;
@Mock
private FullScreenMagnificationController mScreenMagnificationController;
private MagnificationScaleProvider mScaleProvider;
@Captor
@@ -136,6 +139,7 @@ public class MagnificationControllerTest {
mMockResolver = new MockContentResolver();
mMockResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mMockResolver);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
Settings.Secure.putFloatForUser(mMockResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, DEFAULT_SCALE,
CURRENT_USER_ID);

View File

@@ -54,6 +54,8 @@ import android.view.accessibility.IRemoteMagnificationAnimationCallback;
import android.view.accessibility.IWindowMagnificationConnectionCallback;
import android.view.accessibility.MagnificationAnimationCallback;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
@@ -99,12 +101,7 @@ public class WindowMagnificationManagerTest {
mMockCallback, mMockTrace, new MagnificationScaleProvider(mContext));
when(mContext.getContentResolver()).thenReturn(mResolver);
doAnswer((InvocationOnMock invocation) -> {
final boolean connect = (Boolean) invocation.getArguments()[0];
mWindowMagnificationManager.setConnection(
connect ? mMockConnection.getConnection() : null);
return null;
}).when(mMockStatusBarManagerInternal).requestWindowMagnificationConnection(anyBoolean());
stubSetConnection(false);
mResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Settings.Secure.putFloatForUser(mResolver,
@@ -112,6 +109,25 @@ public class WindowMagnificationManagerTest {
CURRENT_USER_ID);
}
private void stubSetConnection(boolean needDelay) {
doAnswer((InvocationOnMock invocation) -> {
final boolean connect = (Boolean) invocation.getArguments()[0];
// Simulates setConnection() called by another process.
if (needDelay) {
final Context context = ApplicationProvider.getApplicationContext();
context.getMainThreadHandler().postDelayed(
() -> {
mWindowMagnificationManager.setConnection(
connect ? mMockConnection.getConnection() : null);
}, 10);
} else {
mWindowMagnificationManager.setConnection(
connect ? mMockConnection.getConnection() : null);
}
return true;
}).when(mMockStatusBarManagerInternal).requestWindowMagnificationConnection(anyBoolean());
}
@Test
public void setConnection_connectionIsNull_wrapperIsNullAndLinkToDeath() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
@@ -464,7 +480,7 @@ public class WindowMagnificationManagerTest {
public void
requestConnectionToNull_disableAllMagnifiersAndRequestWindowMagnificationConnection()
throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
assertTrue(mWindowMagnificationManager.requestConnection(true));
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN);
assertTrue(mWindowMagnificationManager.requestConnection(false));
@@ -499,7 +515,7 @@ public class WindowMagnificationManagerTest {
@Test
public void requestConnectionToNull_expectedGetterResults() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
mWindowMagnificationManager.requestConnection(true);
mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 1, 1);
mWindowMagnificationManager.requestConnection(false);
@@ -512,6 +528,20 @@ public class WindowMagnificationManagerTest {
assertTrue(bounds.isEmpty());
}
@Test
public void enableWindowMagnification_connecting_invokeConnectionMethodAfterConnected()
throws RemoteException {
stubSetConnection(true);
mWindowMagnificationManager.requestConnection(true);
assertTrue(mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 1, 1));
// Invoke enableWindowMagnification if the connection is connected.
verify(mMockConnection.getConnection()).enableWindowMagnification(
eq(TEST_DISPLAY), eq(3f),
eq(1f), eq(1f), eq(0f), eq(0f), notNull());
}
@Test
public void resetAllMagnification_enabledBySameId_windowMagnifiersDisabled() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());