Merge "Waits for windowMagnification connection set when requesting enableWindowMagnification" into tm-dev
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user