Merge "Allow A11yService to customize accessibility focus"
This commit is contained in:
@@ -2883,6 +2883,7 @@ package android.accessibilityservice {
|
||||
method protected void onServiceConnected();
|
||||
method public void onSystemActionsChanged();
|
||||
method public final boolean performGlobalAction(int);
|
||||
method public void setAccessibilityFocusAppearance(int, @ColorInt int);
|
||||
method public void setGestureDetectionPassthroughRegion(int, @NonNull android.graphics.Region);
|
||||
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
|
||||
method public void setTouchExplorationPassthroughRegion(int, @NonNull android.graphics.Region);
|
||||
@@ -54611,6 +54612,8 @@ package android.view.accessibility {
|
||||
method public void addAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, @Nullable android.os.Handler);
|
||||
method public boolean addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
|
||||
method public void addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, @Nullable android.os.Handler);
|
||||
method @ColorInt public int getAccessibilityFocusColor();
|
||||
method public int getAccessibilityFocusStrokeWidth();
|
||||
method @Deprecated public java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
|
||||
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
|
||||
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.accessibilityservice;
|
||||
|
||||
import android.accessibilityservice.GestureDescription.MotionEventGenerator;
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.ColorInt;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -2117,6 +2118,27 @@ public abstract class AccessibilityService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strokeWidth and color of the accessibility focus rectangle.
|
||||
*
|
||||
* @param strokeWidth The stroke width of the rectangle in pixels.
|
||||
* Setting this value to zero results in no focus rectangle being drawn.
|
||||
* @param color The color of the rectangle.
|
||||
*/
|
||||
public void setAccessibilityFocusAppearance(int strokeWidth, @ColorInt int color) {
|
||||
IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.setFocusAppearance(strokeWidth, color);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(LOG_TAG, "Error while setting the strokeWidth and color of the "
|
||||
+ "accessibility focus rectangle", re);
|
||||
re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement to return the implementation of the internal accessibility
|
||||
* service interface.
|
||||
|
||||
@@ -115,4 +115,6 @@ interface IAccessibilityServiceConnection {
|
||||
void setGestureDetectionPassthroughRegion(int displayId, in Region region);
|
||||
|
||||
void setTouchExplorationPassthroughRegion(int displayId, in Region region);
|
||||
|
||||
void setFocusAppearance(int strokeWidth, int color);
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.RenderNode;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManager.DisplayListener;
|
||||
import android.hardware.input.InputManager;
|
||||
@@ -4414,6 +4415,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mView.mContext.getDrawable(value.resourceId);
|
||||
}
|
||||
}
|
||||
// Sets the focus appearance data into the accessibility focus drawable.
|
||||
if (mAttachInfo.mAccessibilityFocusDrawable instanceof GradientDrawable) {
|
||||
final GradientDrawable drawable =
|
||||
(GradientDrawable) mAttachInfo.mAccessibilityFocusDrawable;
|
||||
drawable.setStroke(mAccessibilityManager.getAccessibilityFocusStrokeWidth(),
|
||||
mAccessibilityManager.getAccessibilityFocusColor());
|
||||
}
|
||||
|
||||
return mAttachInfo.mAccessibilityFocusDrawable;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,11 @@ package android.view.accessibility;
|
||||
import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_ENABLE_ACCESSIBILITY_VOLUME;
|
||||
|
||||
import android.Manifest;
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType;
|
||||
import android.accessibilityservice.AccessibilityShortcutInfo;
|
||||
import android.annotation.ColorInt;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -59,6 +61,7 @@ import android.view.IWindow;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent.EventType;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.IntPair;
|
||||
|
||||
@@ -233,6 +236,11 @@ public final class AccessibilityManager {
|
||||
|
||||
private int mPerformingAction = 0;
|
||||
|
||||
/** The stroke width of the focus rectangle in pixels */
|
||||
private int mFocusStrokeWidth;
|
||||
/** The color of the focus rectangle */
|
||||
private int mFocusColor;
|
||||
|
||||
@UnsupportedAppUsage
|
||||
private final ArrayMap<AccessibilityStateChangeListener, Handler>
|
||||
mAccessibilityStateChangeListeners = new ArrayMap<>();
|
||||
@@ -410,6 +418,13 @@ public final class AccessibilityManager {
|
||||
public void setRelevantEventTypes(int eventTypes) {
|
||||
mRelevantEventTypes = eventTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocusAppearance(int strokeWidth, int color) {
|
||||
synchronized (mLock) {
|
||||
updateFocusAppearanceLocked(strokeWidth, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -457,6 +472,7 @@ public final class AccessibilityManager {
|
||||
mHandler = new Handler(context.getMainLooper(), mCallback);
|
||||
mUserId = userId;
|
||||
synchronized (mLock) {
|
||||
initialFocusAppearanceLocked(context.getResources());
|
||||
tryConnectToServiceLocked(service);
|
||||
}
|
||||
}
|
||||
@@ -464,18 +480,26 @@ public final class AccessibilityManager {
|
||||
/**
|
||||
* Create an instance.
|
||||
*
|
||||
* @param context A {@link Context}.
|
||||
* @param handler The handler to use
|
||||
* @param service An interface to the backing service.
|
||||
* @param userId User id under which to run.
|
||||
* @param serviceConnect {@code true} to connect the service or
|
||||
* {@code false} not to connect the service.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public AccessibilityManager(Handler handler, IAccessibilityManager service, int userId) {
|
||||
@VisibleForTesting
|
||||
public AccessibilityManager(Context context, Handler handler, IAccessibilityManager service,
|
||||
int userId, boolean serviceConnect) {
|
||||
mCallback = new MyCallback();
|
||||
mHandler = handler;
|
||||
mUserId = userId;
|
||||
synchronized (mLock) {
|
||||
tryConnectToServiceLocked(service);
|
||||
initialFocusAppearanceLocked(context.getResources());
|
||||
if (serviceConnect) {
|
||||
tryConnectToServiceLocked(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -953,6 +977,32 @@ public final class AccessibilityManager {
|
||||
return recommendedTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the strokeWidth of the focus rectangle. This value can be set by
|
||||
* {@link AccessibilityService}.
|
||||
*
|
||||
* @return The strokeWidth of the focus rectangle in pixels.
|
||||
*
|
||||
*/
|
||||
public int getAccessibilityFocusStrokeWidth() {
|
||||
synchronized (mLock) {
|
||||
return mFocusStrokeWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of the focus rectangle. This value can be set by
|
||||
* {@link AccessibilityService}.
|
||||
*
|
||||
* @return The color of the focus rectangle.
|
||||
*
|
||||
*/
|
||||
public @ColorInt int getAccessibilityFocusColor() {
|
||||
synchronized (mLock) {
|
||||
return mFocusColor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preparers that are registered for an accessibility ID
|
||||
*
|
||||
@@ -1551,6 +1601,7 @@ public final class AccessibilityManager {
|
||||
setStateLocked(IntPair.first(userStateAndRelevantEvents));
|
||||
mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents);
|
||||
updateUiTimeout(service.getRecommendedTimeoutMillis());
|
||||
updateFocusAppearanceLocked(service.getFocusStrokeWidth(), service.getFocusColor());
|
||||
mService = service;
|
||||
} catch (RemoteException re) {
|
||||
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
|
||||
@@ -1634,6 +1685,40 @@ public final class AccessibilityManager {
|
||||
mNonInteractiveUiTimeout = IntPair.second(uiTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stroke width and color of the focus rectangle.
|
||||
*
|
||||
* @param strokeWidth The strokeWidth of the focus rectangle.
|
||||
* @param color The color of the focus rectangle.
|
||||
*/
|
||||
private void updateFocusAppearanceLocked(int strokeWidth, int color) {
|
||||
if (mFocusStrokeWidth == strokeWidth && mFocusColor == color) {
|
||||
return;
|
||||
}
|
||||
mFocusStrokeWidth = strokeWidth;
|
||||
mFocusColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stroke width and color of the focus rectangle to default value.
|
||||
*
|
||||
* @param resource The resources.
|
||||
*/
|
||||
private void initialFocusAppearanceLocked(Resources resource) {
|
||||
try {
|
||||
mFocusStrokeWidth = resource.getDimensionPixelSize(
|
||||
R.dimen.accessibility_focus_highlight_stroke_width);
|
||||
mFocusColor = resource.getColor(R.color.accessibility_focus_highlight_color);
|
||||
} catch (Resources.NotFoundException re) {
|
||||
// Sets the stroke width and color to default value by hardcoded for making
|
||||
// the Talkback can work normally.
|
||||
mFocusStrokeWidth = (int) (4 * resource.getDisplayMetrics().density);
|
||||
mFocusColor = 0xbf39b500;
|
||||
Log.e(LOG_TAG, "Error while initialing the focus appearance data then setting to"
|
||||
+ " default value by hardcoded", re);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the accessibility button within the system navigation area is supported.
|
||||
*
|
||||
|
||||
@@ -92,4 +92,8 @@ interface IAccessibilityManager {
|
||||
void associateEmbeddedHierarchy(IBinder host, IBinder embedded);
|
||||
|
||||
void disassociateEmbeddedHierarchy(IBinder token);
|
||||
|
||||
int getFocusStrokeWidth();
|
||||
|
||||
int getFocusColor();
|
||||
}
|
||||
|
||||
@@ -29,4 +29,6 @@ oneway interface IAccessibilityManagerClient {
|
||||
void notifyServicesStateChanged(long updatedUiTimeout);
|
||||
|
||||
void setRelevantEventTypes(int eventTypes);
|
||||
|
||||
void setFocusAppearance(int strokeWidth, int color);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<stroke
|
||||
android:width="4dp"
|
||||
android:color="@color/accessibility_focus_highlight" />
|
||||
android:width="@dimen/accessibility_focus_highlight_stroke_width"
|
||||
android:color="@color/accessibility_focus_highlight_color" />
|
||||
|
||||
<corners android:radius="2dp" />
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
<color name="keyguard_avatar_nick_color">#ffffffff</color>
|
||||
<color name="keyguard_avatar_frame_pressed_color">#ff35b5e5</color>
|
||||
|
||||
<color name="accessibility_focus_highlight">#bf39b500</color>
|
||||
<color name="accessibility_focus_highlight_color">#bf39b500</color>
|
||||
<color name="autofilled_highlight">#4dffeb3b</color>
|
||||
|
||||
<color name="system_notification_accent_color">#ff607D8B</color>
|
||||
|
||||
@@ -553,6 +553,9 @@
|
||||
<!-- Width of the outline stroke used by the accessibility screen magnification indicator -->
|
||||
<dimen name="accessibility_magnification_indicator_width">4dip</dimen>
|
||||
|
||||
<!-- Width of the outline stroke used by the accessibility focus rectangle -->
|
||||
<dimen name="accessibility_focus_highlight_stroke_width">4dp</dimen>
|
||||
|
||||
<!-- Margin around the various security views -->
|
||||
<dimen name="keyguard_muliuser_selector_margin">8dp</dimen>
|
||||
|
||||
|
||||
@@ -4115,4 +4115,9 @@
|
||||
|
||||
<!-- Component with platform query permissions for AppSearch -->
|
||||
<java-symbol type="string" name="config_defaultAppSearchPlatformQuerierComponent" />
|
||||
|
||||
<!-- Color used by the accessibility focus rectangle -->
|
||||
<java-symbol type="color" name="accessibility_focus_highlight_color" />
|
||||
<!-- Width of the outline stroke used by the accessibility focus rectangle -->
|
||||
<java-symbol type="dimen" name="accessibility_focus_highlight_stroke_width" />
|
||||
</resources>
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.os.UserHandle;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.IntPair;
|
||||
import com.android.server.accessibility.test.MessageCapturingHandler;
|
||||
|
||||
@@ -73,12 +74,18 @@ public class AccessibilityManagerTest {
|
||||
@Mock private IAccessibilityManager mMockService;
|
||||
private MessageCapturingHandler mHandler;
|
||||
private Instrumentation mInstrumentation;
|
||||
private int mFocusStrokeWidthDefaultValue;
|
||||
private int mFocusColorDefaultValue;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mHandler = new MessageCapturingHandler(null);
|
||||
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
mFocusStrokeWidthDefaultValue = mInstrumentation.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width);
|
||||
mFocusColorDefaultValue = mInstrumentation.getContext().getResources().getColor(
|
||||
R.color.accessibility_focus_highlight_color);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -94,8 +101,12 @@ public class AccessibilityManagerTest {
|
||||
when(mMockService.addClient(any(IAccessibilityManagerClient.class), anyInt()))
|
||||
.thenReturn(serviceReturnValue);
|
||||
|
||||
when(mMockService.getFocusStrokeWidth()).thenReturn(mFocusStrokeWidthDefaultValue);
|
||||
when(mMockService.getFocusColor()).thenReturn(mFocusColorDefaultValue);
|
||||
|
||||
AccessibilityManager manager =
|
||||
new AccessibilityManager(mHandler, mMockService, UserHandle.USER_CURRENT);
|
||||
new AccessibilityManager(mInstrumentation.getContext(), mHandler, mMockService,
|
||||
UserHandle.USER_CURRENT, true);
|
||||
|
||||
verify(mMockService).addClient(any(IAccessibilityManagerClient.class), anyInt());
|
||||
mHandler.setCallback(manager.getCallback());
|
||||
@@ -205,4 +216,16 @@ public class AccessibilityManagerTest {
|
||||
|
||||
verify(mMockService).setWindowMagnificationConnection(connection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefaultValueOfFocusAppearanceData() {
|
||||
AccessibilityManager manager =
|
||||
new AccessibilityManager(mInstrumentation.getContext(), mHandler, null,
|
||||
UserHandle.USER_CURRENT, false);
|
||||
|
||||
assertEquals(mFocusStrokeWidthDefaultValue,
|
||||
manager.getAccessibilityFocusStrokeWidth());
|
||||
assertEquals(mFocusColorDefaultValue,
|
||||
manager.getAccessibilityFocusColor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,4 +161,6 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {}
|
||||
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {}
|
||||
|
||||
public void setFocusAppearance(int strokeWidth, int color) {}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -148,7 +149,8 @@ public class AccessibilityShortcutControllerTest {
|
||||
|
||||
// Use the extra level of indirection in the object to mock framework objects
|
||||
AccessibilityManager accessibilityManager =
|
||||
new AccessibilityManager(mHandler, mAccessibilityManagerService, 0);
|
||||
new AccessibilityManager(InstrumentationRegistry.getContext(), mHandler,
|
||||
mAccessibilityManagerService, 0, true);
|
||||
when(mFrameworkObjectProvider.getAccessibilityManagerInstance(mContext))
|
||||
.thenReturn(accessibilityManager);
|
||||
when(mContext.getSystemService(Context.ACCESSIBILITY_SERVICE))
|
||||
|
||||
@@ -1797,4 +1797,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
|
||||
mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocusAppearance(int strokeWidth, int color) { }
|
||||
}
|
||||
|
||||
@@ -1968,6 +1968,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
// Update the capabilities before the mode.
|
||||
updateMagnificationCapabilitiesSettingsChangeLocked(userState);
|
||||
updateMagnificationModeChangeSettingsLocked(userState);
|
||||
updateFocusAppearanceDataLocked(userState);
|
||||
}
|
||||
|
||||
private void updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState) {
|
||||
@@ -3012,6 +3013,30 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stroke width of the focus rectangle.
|
||||
* @return The stroke width.
|
||||
*/
|
||||
public int getFocusStrokeWidth() {
|
||||
synchronized (mLock) {
|
||||
final AccessibilityUserState userState = getCurrentUserStateLocked();
|
||||
|
||||
return userState.getFocusStrokeWidthLocked();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of the focus rectangle.
|
||||
* @return The color.
|
||||
*/
|
||||
public int getFocusColor() {
|
||||
synchronized (mLock) {
|
||||
final AccessibilityUserState userState = getCurrentUserStateLocked();
|
||||
|
||||
return userState.getFocusColorLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
|
||||
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
|
||||
@@ -3623,4 +3648,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFocusAppearanceDataLocked(AccessibilityUserState userState) {
|
||||
if (userState.mUserId != mCurrentUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMainHandler.post(() -> {
|
||||
broadcastToClients(userState, ignoreRemoteException(client -> {
|
||||
client.mCallback.setFocusAppearance(userState.getFocusStrokeWidthLocked(),
|
||||
userState.getFocusColorLocked());
|
||||
}));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,8 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
|
||||
AccessibilityUserState userState = mUserStateWeakReference.get();
|
||||
if (userState == null) return;
|
||||
userState.removeServiceLocked(this);
|
||||
userState.resetFocusAppearanceLocked();
|
||||
mSystemSupport.onClientChangeLocked(false);
|
||||
mSystemSupport.getFullScreenMagnificationController().resetAllIfNeeded(mId);
|
||||
mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), -1,
|
||||
userState.mUserId);
|
||||
@@ -144,6 +146,7 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
userState.resetFocusAppearanceLocked();
|
||||
mSystemSupport.onClientChangeLocked(false);
|
||||
}
|
||||
}
|
||||
@@ -310,6 +313,7 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
|
||||
AccessibilityUserState userState = mUserStateWeakReference.get();
|
||||
if (userState != null) {
|
||||
userState.serviceDisconnectedLocked(this);
|
||||
userState.resetFocusAppearanceLocked();
|
||||
}
|
||||
resetLocked();
|
||||
mSystemSupport.getFullScreenMagnificationController().resetAllIfNeeded(mId);
|
||||
@@ -391,4 +395,32 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocusAppearance(int strokeWidth, int color) {
|
||||
AccessibilityUserState userState = mUserStateWeakReference.get();
|
||||
if (userState == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
if (!hasRightsToCurrentUserLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (userState.getFocusStrokeWidthLocked() == strokeWidth
|
||||
&& userState.getFocusColorLocked() == color) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sets the appearance data in the A11yUserState.
|
||||
userState.setFocusAppearanceLocked(strokeWidth, color);
|
||||
// Updates the appearance data in the A11yManager.
|
||||
mSystemSupport.onClientChangeLocked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import android.util.Slog;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.IAccessibilityManagerClient;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.accessibility.AccessibilityShortcutController;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -122,6 +123,15 @@ class AccessibilityUserState {
|
||||
// The magnification capabilities used to know magnification mode could be switched.
|
||||
private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
|
||||
|
||||
/** The stroke width of the focus rectangle in pixels */
|
||||
private int mFocusStrokeWidth;
|
||||
/** The color of the focus rectangle */
|
||||
private int mFocusColor;
|
||||
// The default value of the focus stroke width.
|
||||
private final int mFocusStrokeWidthDefaultValue;
|
||||
// The default value of the focus color.
|
||||
private final int mFocusColorDefaultValue;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@SoftKeyboardShowMode
|
||||
@@ -140,6 +150,12 @@ class AccessibilityUserState {
|
||||
mUserId = userId;
|
||||
mContext = context;
|
||||
mServiceInfoChangeListener = serviceInfoChangeListener;
|
||||
mFocusStrokeWidthDefaultValue = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.accessibility_focus_highlight_stroke_width);
|
||||
mFocusColorDefaultValue = mContext.getResources().getColor(
|
||||
R.color.accessibility_focus_highlight_color);
|
||||
mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
|
||||
mFocusColor = mFocusColorDefaultValue;
|
||||
}
|
||||
|
||||
boolean isHandlingAccessibilityEventsLocked() {
|
||||
@@ -178,6 +194,7 @@ class AccessibilityUserState {
|
||||
mUserNonInteractiveUiTimeout = 0;
|
||||
mUserInteractiveUiTimeout = 0;
|
||||
mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
|
||||
resetFocusAppearanceLocked();
|
||||
}
|
||||
|
||||
void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
|
||||
@@ -880,4 +897,40 @@ class AccessibilityUserState {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stroke width of the focus rectangle.
|
||||
* @return The stroke width.
|
||||
*/
|
||||
public int getFocusStrokeWidthLocked() {
|
||||
return mFocusStrokeWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of the focus rectangle.
|
||||
* @return The color.
|
||||
*/
|
||||
public int getFocusColorLocked() {
|
||||
return mFocusColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stroke width and color of the focus rectangle.
|
||||
*
|
||||
* @param strokeWidth The strokeWidth of the focus rectangle.
|
||||
* @param color The color of the focus rectangle.
|
||||
*/
|
||||
public void setFocusAppearanceLocked(int strokeWidth, int color) {
|
||||
mFocusStrokeWidth = strokeWidth;
|
||||
mFocusColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the stroke width and color of the focus rectangle to the default value.
|
||||
*
|
||||
*/
|
||||
public void resetFocusAppearanceLocked() {
|
||||
mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
|
||||
mFocusColor = mFocusColorDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
@@ -94,6 +95,8 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
|
||||
@Mock private IAccessibilityServiceClient mMockServiceClient;
|
||||
@Mock private WindowMagnificationManager mMockWindowMagnificationMgr;
|
||||
@Mock private MagnificationController mMockMagnificationController;
|
||||
@Mock private Resources mMockResources;
|
||||
|
||||
private AccessibilityUserState mUserState;
|
||||
|
||||
private MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
|
||||
@@ -121,6 +124,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
|
||||
mMockA11yDisplayListener,
|
||||
mMockMagnificationController);
|
||||
|
||||
mMockResources = mock(Resources.class);
|
||||
when(mMockContext.getResources()).thenReturn(mMockResources);
|
||||
|
||||
final AccessibilityUserState userState = new AccessibilityUserState(
|
||||
mA11yms.getCurrentUserIdLocked(), mMockContext, mA11yms);
|
||||
mA11yms.mUserStates.put(mA11yms.getCurrentUserIdLocked(), userState);
|
||||
|
||||
@@ -42,11 +42,16 @@ import static org.mockito.Mockito.when;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.provider.Settings;
|
||||
import android.test.mock.MockContentResolver;
|
||||
import android.testing.DexmakerShareClassLoaderRule;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -90,8 +95,13 @@ public class AccessibilityUserStateTest {
|
||||
|
||||
private AccessibilityUserState mUserState;
|
||||
|
||||
private int mFocusStrokeWidthDefaultValue;
|
||||
private int mFocusColorDefaultValue;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final Resources resources = InstrumentationRegistry.getContext().getResources();
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
FakeSettingsProvider.clearSettingsProvider();
|
||||
mMockResolver = new MockContentResolver();
|
||||
@@ -99,6 +109,11 @@ public class AccessibilityUserStateTest {
|
||||
when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
|
||||
when(mMockServiceInfo.getComponentName()).thenReturn(COMPONENT_NAME);
|
||||
when(mMockConnection.getServiceInfo()).thenReturn(mMockServiceInfo);
|
||||
when(mMockContext.getResources()).thenReturn(resources);
|
||||
|
||||
mFocusStrokeWidthDefaultValue =
|
||||
resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width);
|
||||
mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color);
|
||||
|
||||
mUserState = new AccessibilityUserState(USER_ID, mMockContext, mMockListener);
|
||||
}
|
||||
@@ -129,6 +144,7 @@ public class AccessibilityUserStateTest {
|
||||
mUserState.setUserNonInteractiveUiTimeoutLocked(30);
|
||||
mUserState.setUserInteractiveUiTimeoutLocked(30);
|
||||
mUserState.setMagnificationModeLocked(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
|
||||
mUserState.setFocusAppearanceLocked(20, Color.BLUE);
|
||||
|
||||
mUserState.onSwitchToAnotherUserLocked();
|
||||
|
||||
@@ -150,6 +166,8 @@ public class AccessibilityUserStateTest {
|
||||
assertEquals(0, mUserState.getUserInteractiveUiTimeoutLocked());
|
||||
assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
|
||||
mUserState.getMagnificationModeLocked());
|
||||
assertEquals(mFocusStrokeWidthDefaultValue, mUserState.getFocusStrokeWidthLocked());
|
||||
assertEquals(mFocusColorDefaultValue, mUserState.getFocusColorLocked());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -350,6 +368,21 @@ public class AccessibilityUserStateTest {
|
||||
mUserState.getMagnificationModeLocked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setFocusAppearanceData_returnExpectedFocusAppearanceData() {
|
||||
final int focusStrokeWidthValue = 100;
|
||||
final int focusColorValue = Color.BLUE;
|
||||
|
||||
assertEquals(mFocusStrokeWidthDefaultValue, mUserState.getFocusStrokeWidthLocked());
|
||||
assertEquals(mFocusColorDefaultValue, mUserState.getFocusColorLocked());
|
||||
|
||||
mUserState.setFocusAppearanceLocked(focusStrokeWidthValue, focusColorValue);
|
||||
|
||||
assertEquals(focusStrokeWidthValue, mUserState.getFocusStrokeWidthLocked());
|
||||
assertEquals(focusColorValue, mUserState.getFocusColorLocked());
|
||||
|
||||
}
|
||||
|
||||
private int getSecureIntForUser(String key, int userId) {
|
||||
return Settings.Secure.getIntForUser(mMockResolver, key, -1, userId);
|
||||
}
|
||||
|
||||
@@ -153,7 +153,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
|
||||
AccessibilityEvent.TYPES_ALL_MASK);
|
||||
when(mAccessibilityService.addClient(any(), anyInt())).thenReturn(serviceReturnValue);
|
||||
AccessibilityManager accessibilityManager =
|
||||
new AccessibilityManager(Handler.getMain(), mAccessibilityService, 0);
|
||||
new AccessibilityManager(getContext(), Handler.getMain(), mAccessibilityService,
|
||||
0, true);
|
||||
verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
|
||||
assertTrue(accessibilityManager.isEnabled());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user