Introduce accessibility large pointer icons.

This patch does the following things:
- add new graphic assets of large icons for accessibility needs
  (imported from ChromeOS data)
- add the logic to choose the set of normal icons or accessibility icons
- make InputManagerService to observe the settings change, so that
  it can reload the new resources

This patch misses non-1x graphic though, because ChromeOS doesn't
have such data.

Bug: 25778857
Change-Id: Ia5f95d47f50b3f6eea555c3af8069bc6bae0b400
This commit is contained in:
Jun Mukai
2015-11-24 11:25:52 -08:00
parent 28860b7570
commit 19a5601979
50 changed files with 240 additions and 44 deletions

View File

@@ -4919,6 +4919,15 @@ public final class Settings {
public static final String ACCESSIBILITY_AUTOCLICK_DELAY =
"accessibility_autoclick_delay";
/**
* Whether or not larger size icons are used for the pointer of mouse/trackpad for
* accessibility.
* (0 = false, 1 = true)
* @hide
*/
public static final String ACCESSIBILITY_LARGE_POINTER_ICON =
"accessibility_large_pointer_icon";
/**
* The timeout for considering a press to be a long press in milliseconds.
* @hide

View File

@@ -16,6 +16,8 @@
package android.view;
import android.os.UserHandle;
import android.provider.Settings;
import com.android.internal.util.XmlUtils;
import android.annotation.XmlRes;
@@ -199,9 +201,14 @@ public final class PointerIcon implements Parcelable {
styleIndex = getSystemIconStyleIndex(STYLE_DEFAULT);
}
int accessibilityConfig = Settings.Secure.getIntForUser(
context.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
0, UserHandle.USER_CURRENT);
int defStyle = (accessibilityConfig == 1) ?
com.android.internal.R.style.LargePointer : com.android.internal.R.style.Pointer;
TypedArray a = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.Pointer,
com.android.internal.R.attr.pointerStyle, 0);
0, defStyle);
int resourceId = a.getResourceId(styleIndex, -1);
a.recycle();

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_alias_large"
android:hotSpotX="19dp"
android:hotSpotY="11dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_all_scroll_large"
android:hotSpotX="32dp"
android:hotSpotY="31dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_arrow_large"
android:hotSpotX="10dp"
android:hotSpotY="10dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_cell_large"
android:hotSpotX="30dp"
android:hotSpotY="30dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_context_menu_large"
android:hotSpotX="11dp"
android:hotSpotY="11dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_copy_large"
android:hotSpotX="10dp"
android:hotSpotY="10dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_crosshair_large"
android:hotSpotX="31dp"
android:hotSpotY="30dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_grab_large"
android:hotSpotX="21dp"
android:hotSpotY="11dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_grabbing_large"
android:hotSpotX="20dp"
android:hotSpotY="12dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_hand_large"
android:hotSpotX="25dp"
android:hotSpotY="7dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_help_large"
android:hotSpotX="10dp"
android:hotSpotY="11dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_horizontal_double_arrow_large"
android:hotSpotX="35dp"
android:hotSpotY="29dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_nodrop_large"
android:hotSpotX="10dp"
android:hotSpotY="10dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_text_large"
android:hotSpotX="30dp"
android:hotSpotY="32dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_top_left_diagonal_double_arrow_large"
android:hotSpotX="32dp"
android:hotSpotY="30dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_top_right_diagonal_double_arrow_large"
android:hotSpotX="32dp"
android:hotSpotY="31dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_vertical_double_arrow_large"
android:hotSpotX="29dp"
android:hotSpotY="32dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_vertical_text_large"
android:hotSpotX="32dp"
android:hotSpotY="30dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_zoom_in_large"
android:hotSpotX="25dp"
android:hotSpotY="26dp" />

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:bitmap="@drawable/pointer_zoom_out_large"
android:hotSpotX="26dp"
android:hotSpotY="26dp" />

View File

@@ -1026,9 +1026,6 @@ i
<!-- ============== -->
<eat-comment />
<!-- Reference to the Pointer style -->
<attr name="pointerStyle" format="reference" />
<!-- The drawable for accessibility focused views. -->
<attr name="accessibilityFocusedDrawable" format="reference" />

View File

@@ -1368,6 +1368,42 @@ please see styles_device_defaults.xml.
<item name="pointerIconGrabbing">@drawable/pointer_grabbing_icon</item>
</style>
<style name="LargePointer">
<item name="pointerIconArrow">@drawable/pointer_arrow_large_icon</item>
<item name="pointerIconSpotHover">@drawable/pointer_spot_hover_icon</item>
<item name="pointerIconSpotTouch">@drawable/pointer_spot_touch_icon</item>
<item name="pointerIconSpotAnchor">@drawable/pointer_spot_anchor_icon</item>
<item name="pointerIconHand">@drawable/pointer_hand_large_icon</item>
<item name="pointerIconContextMenu">@drawable/pointer_context_menu_large_icon</item>
<item name="pointerIconHelp">@drawable/pointer_help_large_icon</item>
<!-- TODO: create large wait icon. -->
<item name="pointerIconWait">@drawable/pointer_wait_icon</item>
<item name="pointerIconCell">@drawable/pointer_cell_large_icon</item>
<item name="pointerIconCrosshair">@drawable/pointer_crosshair_large_icon</item>
<item name="pointerIconText">@drawable/pointer_text_large_icon</item>
<item name="pointerIconVerticalText">@drawable/pointer_vertical_text_large_icon</item>
<item name="pointerIconAlias">@drawable/pointer_alias_large_icon</item>
<item name="pointerIconCopy">@drawable/pointer_copy_large_icon</item>
<item name="pointerIconAllScroll">@drawable/pointer_all_scroll_large_icon</item>
<item name="pointerIconNodrop">@drawable/pointer_nodrop_large_icon</item>
<item name="pointerIconHorizontalDoubleArrow">
@drawable/pointer_horizontal_double_arrow_large_icon
</item>
<item name="pointerIconVerticalDoubleArrow">
@drawable/pointer_vertical_double_arrow_large_icon
</item>
<item name="pointerIconTopRightDiagonalDoubleArrow">
@drawable/pointer_top_right_diagonal_double_arrow_large_icon
</item>
<item name="pointerIconTopLeftDiagonalDoubleArrow">
@drawable/pointer_top_left_diagonal_double_arrow_large_icon
</item>
<item name="pointerIconZoomIn">@drawable/pointer_zoom_in_large_icon</item>
<item name="pointerIconZoomOut">@drawable/pointer_zoom_out_large_icon</item>
<item name="pointerIconGrab">@drawable/pointer_grab_large_icon</item>
<item name="pointerIconGrabbing">@drawable/pointer_grabbing_large_icon</item>
</style>
<!-- Wifi dialog styles -->
<!-- @hide -->
<style name="wifi_item">

View File

@@ -231,7 +231,6 @@
<java-symbol type="attr" name="gestureOverlayViewStyle" />
<java-symbol type="attr" name="keyboardViewStyle" />
<java-symbol type="attr" name="numberPickerStyle" />
<java-symbol type="attr" name="pointerStyle" />
<java-symbol type="attr" name="preferenceFrameLayoutStyle" />
<java-symbol type="attr" name="searchDialogTheme" />
<java-symbol type="attr" name="textAppearanceAutoCorrectionSuggestion" />
@@ -1428,6 +1427,8 @@
<java-symbol type="style" name="Theme.DeviceDefault.Dialog.NoFrame" />
<java-symbol type="style" name="Theme.IconMenu" />
<java-symbol type="style" name="Theme.DeviceDefault.VoiceInteractionSession" />
<java-symbol type="style" name="Pointer" />
<java-symbol type="style" name="LargePointer" />
<java-symbol type="attr" name="mediaRouteButtonStyle" />
<java-symbol type="attr" name="externalRouteEnabledDrawable" />

View File

@@ -428,9 +428,6 @@ please see themes_device_defaults.xml.
<item name="fastScrollOverlayPosition">floating</item>
<item name="fastScrollTextColor">@color/primary_text_dark</item>
<!-- Pointer style -->
<item name="pointerStyle">@style/Pointer</item>
<!-- Accessibility focused drawable -->
<item name="accessibilityFocusedDrawable">@drawable/view_accessibility_focused</item>

View File

@@ -91,7 +91,14 @@ PointerController::PointerController(const sp<PointerControllerPolicyInterface>&
mLocked.buttonState = 0;
mPolicy->loadPointerIcon(&mLocked.pointerIcon);
loadResources();
if (mLocked.pointerIcon.isValid()) {
mLocked.pointerIconChanged = true;
updatePointerLocked();
}
}
PointerController::~PointerController() {
@@ -325,6 +332,23 @@ void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout
}
}
void PointerController::reloadPointerResources() {
AutoMutex _l(mLock);
loadResources();
if (mLocked.presentation == PRESENTATION_POINTER) {
mLocked.additionalMouseResources.clear();
mLocked.animationResources.clear();
mPolicy->loadPointerIcon(&mLocked.pointerIcon);
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
&mLocked.animationResources);
}
mLocked.presentationChanged = true;
updatePointerLocked();
}
void PointerController::setDisplayViewport(int32_t width, int32_t height, int32_t orientation) {
AutoMutex _l(mLock);
@@ -415,15 +439,6 @@ void PointerController::updatePointerShape(int32_t iconId) {
}
}
void PointerController::setPointerIcon(const SpriteIcon& icon) {
AutoMutex _l(mLock);
mLocked.pointerIcon = icon.copy();
mLocked.pointerIconChanged = true;
updatePointerLocked();
}
void PointerController::handleMessage(const Message& message) {
switch (message.what) {
case MSG_INACTIVITY_TIMEOUT:

View File

@@ -62,6 +62,7 @@ protected:
virtual ~PointerControllerPolicyInterface() { }
public:
virtual void loadPointerIcon(SpriteIcon* icon) = 0;
virtual void loadPointerResources(PointerResources* outResources) = 0;
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
std::map<int32_t, PointerAnimation>* outAnimationResources) = 0;
@@ -105,8 +106,8 @@ public:
void updatePointerShape(int32_t iconId);
void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
void setPointerIcon(const SpriteIcon& icon);
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void reloadPointerResources();
private:
static const size_t MAX_RECYCLED_SPRITES = 12;

View File

@@ -207,6 +207,7 @@ public class InputManagerService extends IInputManager.Stub
private static native String nativeDump(long ptr);
private static native void nativeMonitor(long ptr);
private static native void nativeSetPointerIconShape(long ptr, int iconId);
private static native void nativeReloadPointerIcons(long ptr);
// Input event injection constants defined in InputDispatcher.h.
private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -306,12 +307,14 @@ public class InputManagerService extends IInputManager.Stub
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
nativeReloadPointerIcons(mPtr);
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
@@ -1348,6 +1351,17 @@ public class InputManagerService extends IInputManager.Stub
}, UserHandle.USER_ALL);
}
private void registerAccessibilityLargePointerSettingObserver() {
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON), true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
nativeReloadPointerIcons(mPtr);
}
}, UserHandle.USER_ALL);
}
private int getShowTouchesSetting(int defaultValue) {
int result = defaultValue;
try {
@@ -1417,11 +1431,11 @@ public class InputManagerService extends IInputManager.Stub
}
}
// Binder call
@Override
public void setPointerIconShape(int iconId) {
nativeSetPointerIconShape(mPtr, iconId);
}
// Binder call
@Override
public void setPointerIconShape(int iconId) {
nativeSetPointerIconShape(mPtr, iconId);
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

View File

@@ -205,6 +205,7 @@ public:
void setInteractive(bool interactive);
void reloadCalibration();
void setPointerIconShape(int32_t iconId);
void reloadPointerIcons();
/* --- InputReaderPolicyInterface implementation --- */
@@ -242,6 +243,7 @@ public:
/* --- PointerControllerPolicyInterface implementation --- */
virtual void loadPointerIcon(SpriteIcon* icon);
virtual void loadPointerResources(PointerResources* outResources);
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
std::map<int32_t, PointerAnimation>* outAnimationResources);
@@ -477,22 +479,6 @@ sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32
v.logicalBottom - v.logicalTop,
v.orientation);
JNIEnv* env = jniEnv();
jobject pointerIconObj = env->CallObjectMethod(mServiceObj,
gServiceClassInfo.getPointerIcon);
if (!checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
PointerIcon pointerIcon;
status_t status = android_view_PointerIcon_load(env, pointerIconObj,
mContextObj, &pointerIcon);
if (!status && !pointerIcon.isNullIcon()) {
controller->setPointerIcon(SpriteIcon(pointerIcon.bitmap,
pointerIcon.hotSpotX, pointerIcon.hotSpotY));
} else {
controller->setPointerIcon(SpriteIcon());
}
env->DeleteLocalRef(pointerIconObj);
}
updateInactivityTimeoutLocked(controller);
}
return controller;
@@ -789,12 +775,19 @@ void NativeInputManager::reloadCalibration() {
}
void NativeInputManager::setPointerIconShape(int32_t iconId) {
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
if (controller != NULL) {
// Use 0 (the default icon) for ARROW.
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
if (controller != NULL) {
controller->updatePointerShape(iconId);
}
}
}
void NativeInputManager::reloadPointerIcons() {
AutoMutex _l(mLock);
sp<PointerController> controller = mLocked.pointerController.promote();
if (controller != NULL) {
controller->reloadPointerResources();
}
}
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
@@ -1036,6 +1029,25 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
return result;
}
void NativeInputManager::loadPointerIcon(SpriteIcon* icon) {
JNIEnv* env = jniEnv();
ScopedLocalRef<jobject> pointerIconObj(env, env->CallObjectMethod(
mServiceObj, gServiceClassInfo.getPointerIcon));
if (checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
return;
}
PointerIcon pointerIcon;
status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(),
mContextObj, &pointerIcon);
if (!status && !pointerIcon.isNullIcon()) {
*icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
} else {
*icon = SpriteIcon();
}
}
void NativeInputManager::loadPointerResources(PointerResources* outResources) {
JNIEnv* env = jniEnv();
@@ -1420,6 +1432,11 @@ static void nativeSetPointerIconShape(JNIEnv* /* env */, jclass /* clazz */, jlo
im->setPointerIconShape(iconId);
}
static void nativeReloadPointerIcons(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->reloadPointerIcons();
}
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -1480,6 +1497,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
(void*) nativeMonitor },
{ "nativeSetPointerIconShape", "(JI)V",
(void*) nativeSetPointerIconShape },
{ "nativeReloadPointerIcons", "(J)V",
(void*) nativeReloadPointerIcons },
};
#define FIND_CLASS(var, className) \