From 3822896e226567c6cd3ef84518d318abd33a7624 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Tue, 29 Jan 2013 01:04:35 -0800 Subject: [PATCH] Remove "enhance web scripts" from settings and make it requested by plug-ins. Currently we have an "enhance web accessibility" setting that has to be enabled to make sure web content is accessible. We added the setting to get user consent because we are injecting JavaScript-based screen-reader pulled from the Google infrastructure. However, many users do not know that and (as expected) do not read the user documentation, resulting in critique for lacking accessibility support in WebViews with JavaScript enabled (Browser, Gmail, etc). To smoothen the user experience now "enhance web accessibility" is a feature an accessibility plug-in can request, similarly to explore by touch. Now a user does not need to know that she has to explicitly enable the setting and web accessibility will work out-of-the-box. Before we were showing a dialog when a plug-in tries to put the device in a touch exploration mode. However, now that we have one more feature a plug-in can request, showing two dialogs (assume a plug-in wants both features) will mean that a user should potentially deal with three dialogs, one for enabling the service, and one for each feature. We could merge the dialogs but still the user has to poke two dialogs. It seems that the permission mechanism is a perfect fit for getting user permission for an app to do something, in this case to enable an accessibility feature. We need a separate permission for explore by touch and enhance web accessibility since the former changes the interaction model and the latter injects JavaScript in web pages. It is critical to get user consent for the script injection part so we need a well-documented permission rather a vague umbrella permission for poking accessibility features. To allow better grouping of the accessibility permissions this patch adds a permission group as well. bug:8089372 Change-Id: Ic125514c34f191aea0416a469e4b3481ab3200b9 --- api/current.txt | 6 +- .../AccessibilityServiceInfo.java | 14 +- core/java/android/provider/Settings.java | 1 + core/res/AndroidManifest.xml | 27 ++- .../perm_group_accessibility_features.png | Bin 0 -> 1223 bytes .../perm_group_accessibility_features.png | Bin 0 -> 845 bytes .../perm_group_accessibility_features.png | Bin 0 -> 1631 bytes core/res/res/values/attrs.xml | 2 + core/res/res/values/strings.xml | 38 ++-- .../providers/settings/DatabaseHelper.java | 18 +- .../AccessibilityManagerService.java | 215 +++++++----------- 11 files changed, 165 insertions(+), 156 deletions(-) create mode 100755 core/res/res/drawable-hdpi/perm_group_accessibility_features.png create mode 100755 core/res/res/drawable-mdpi/perm_group_accessibility_features.png create mode 100644 core/res/res/drawable-xhdpi/perm_group_accessibility_features.png diff --git a/api/current.txt b/api/current.txt index fab07f6985e39..088255426faab 100644 --- a/api/current.txt +++ b/api/current.txt @@ -36,6 +36,8 @@ package android { field public static final java.lang.String CALL_PHONE = "android.permission.CALL_PHONE"; field public static final java.lang.String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED"; field public static final java.lang.String CAMERA = "android.permission.CAMERA"; + field public static final java.lang.String CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = "android.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; + field public static final java.lang.String CAN_REQUEST_TOUCH_EXPLORATION_MODE = "android.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE"; field public static final java.lang.String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE"; field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION"; field public static final java.lang.String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE"; @@ -141,6 +143,7 @@ package android { public static final class Manifest.permission_group { ctor public Manifest.permission_group(); + field public static final java.lang.String ACCESSIBILITY_FEATURES = "android.permission-group.ACCESSIBILITY_FEATURES"; field public static final java.lang.String ACCOUNTS = "android.permission-group.ACCOUNTS"; field public static final java.lang.String AFFECTS_BATTERY = "android.permission-group.AFFECTS_BATTERY"; field public static final java.lang.String APP_INFO = "android.permission-group.APP_INFO"; @@ -2104,7 +2107,8 @@ package android.accessibilityservice { field public static final int FEEDBACK_SPOKEN = 1; // 0x1 field public static final int FEEDBACK_VISUAL = 8; // 0x8 field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2 - field public static final int FLAG_REPORT_VIEW_IDS = 8; // 0x8 + field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10 + field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8 field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4 field public int eventTypes; field public int feedbackType; diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 2006bc73f807a..2dc0501448ea8 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -152,6 +152,18 @@ public class AccessibilityServiceInfo implements Parcelable { */ public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE= 0x0000004; + /** + * This flag requests from the system to enable web accessibility enhancing + * extensions. Such extensions aim to provide improved accessibility support + * for content presented in a {@link android.webkit.WebView}. An example of such + * an extension is injecting JavaScript from Google. The system will enable + * enhanced web accessibility if there is at least one accessibility service + * that has this flag set. Hence, clearing this flag does not guarantee that the + * device will not have enhanced web accessibility enabled since there may be + * another enabled service that requested it. + */ + public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; + /** * This flag requests that the {@link AccessibilityNodeInfo}s obtained * by an {@link AccessibilityService} contain the id of the source view. @@ -159,7 +171,7 @@ public class AccessibilityServiceInfo implements Parcelable { * form "package:id/name", for example "foo.bar:id/my_list", and it is * useful for UI test automation. This flag is not set by default. */ - public static final int FLAG_REPORT_VIEW_IDS = 0x00000008; + public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; /** * The event types an {@link AccessibilityService} is interested in. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3d850cfb022dd..be21fb433f961 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3351,6 +3351,7 @@ public final class Settings { * * @hide */ + @Deprecated public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES = "touch_exploration_granted_accessibility_services"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index aafc4bf9906d6..7a51c0c88f581 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -532,6 +532,31 @@ android:label="@string/permlab_addVoicemail" android:description="@string/permdesc_addVoicemail" /> + + + + + + + + + + + + + @@ -1724,7 +1749,7 @@ android:description="@string/permdesc_bindInputMethod" android:protectionLevel="signature" /> - GLRQ~cn|an%^$^Fiw>Q51 zSJ9}H@|o0^vRlvR$m_pn&iLO|?h{(*cw5wPYo`{Xm*CK_7Rl zT79nL$GlzZ=81fqFg>Jp-38gUy3i>TCVt}CaEhh>`w51533EapXa;S1sK=vqxhFM& zXU03DI|myze$QT`CHI#@g|%+ciSLYMUrrpqDeul5a8)|-@~VzbO-)7%>F;~nv#Xs< zPQJ5tjq(v4i95u981{WPJmz*KV&OsG!lO#AtFncc zZ24g!wQKI`pLS9^+IH_SdgWI%W3|%9n|?uAit`*cXXQoLUeXLLEb(v zX4M^U*(=KViXM2Mn>>N}`$y^1ftPf?GM%-Edd@R@d%A+c!VAR=jV%8jeYUVZW8ocm zTQ`dJ--GW(ViV?woKCvoH=!hL`J?}P_nhBn@s6+Ld051gpg)r)ZJsS$bNaUHb^a6G z5=Z{7TUpstT)*Xtc@mq{qqBNP*2nKoe!W(<%HjdfXOZs-=M3hs&oaq0KCHPcbK-7|ZK6bI|bd>nBg!6#&o1|Vb{!fg%Ph<#rWPVm}miN2(vij5~nVy)~FRt-l zro`i3@)G*3et){^qoeBYF-7x#Nazp{QObFs!#@W}J4W%2r5>(zaH zd6Z}A3(Fo!&plps{><64k0YY@DYX4h*w_AO!t!b^vv7aw;MK1rE0!K})s*Dz`@~UR z#H^V+?MK(-8V^6Oxaa229Wp%wXJi^3^b3nv%BwQ>@Sb0%3tEve6CvJ8c~vxSdwa$T$Bo=7>o=I4RsBSbPbF{3{9+z zEv<|VbPX)53=F37HJhPm$jwj5OshoKU~Xk>0@1*CRbLCJK@wy`aDG}zd16s2gJVj5 gQmTSyZen_BP-C;$Ke literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/perm_group_accessibility_features.png b/core/res/res/drawable-mdpi/perm_group_accessibility_features.png new file mode 100755 index 0000000000000000000000000000000000000000..ba86d3d4aec66e4a733d36b4f909f55b08235d60 GIT binary patch literal 845 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE>K&jr;B5V$ML08_hySaiX5%qyt~oCCt!lfA~g?@ zBN{7u!=gC3l$^F~-r^~^VcW(1jsiJr)(AOnxNyizc~R?xLr#y}w+OUIxNv{nyZ!g( z8J?f)zU@`Gm-qafZSlFCzK6jbYQir;R+x_v%?WHfp6?Uk&52Iwxwl z*+AU*`Pw~N&&0&o*o|(obSPNlI@hYPv7gA8Eb!>M=euG#iCZVq?|d+`K5{UMC+Wl1 zUsn_PBUkAkl?=`Aa?KA7eErEH_>Y>(|GvQ8E2Etl+9sqjsAUKR-4tQSXJc5h&9yb3 z(PF|URRhig%d5l+1B?>PyKPdXy*U*QZIwvn|IjSj5ghoKQBu@+4#TquhJ;CmT1HVm z8)SbRx~0I+a*w&7Ex(3cO=2PApA>P+4-?fQ<2gePD6KwFSoVoe;yIV)hJI~^nvUwD zXLS0af3qC9S-s*_>iZSG=8IRJ>uOaLZTIb1(|aGAsexUSG+Pu|jVot4WwJYG$`wTkh_(nM|zYfm{ZW1{#c~&B42v70! zVjTl-;YRn8|DH;!{#QLV96lGeD{SHGIZxhnXlF$RN8Q?zIP=%U?dURSzV2#gpQ1j&$L3Mgrq!D^ZOIIdEqZ_L z>1(6DU3aeadd)3&mw#Qwpwu0>{^z04`d>HM=e;d%eIfOtSMrnqXOH0-{<_>X0pE|b z2OC z7#SEE>KYj78W@KdnphcIS{WPY8dz8v7)<4BHbc>no1c=IR*9~`+{)MlqJi(Kz7|k} vB*=!~{Irtt#G+IN$CUh}R0Yr6#Prml)Wnp^!jq{sKt&9mu6{1-oD!M<@r70w literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png b/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png new file mode 100644 index 0000000000000000000000000000000000000000..2fec7a3e8aa935e01ef6dc08e61b86c633c323c7 GIT binary patch literal 1631 zcmV-l2B7(gP)ht(u000GNNklvOY1`)Odkp@B#_{P5wQpoAJiB%iN+{SsA3W|f9Bq^KOfFMXYQT3nS0K?T7AeG zX6BxA*52!P*7~ir_TCpR$tC%LCA1x2|47H0VnDL7%x8dDj<($tlL1KY9to^t6>*7I zzJC#exXlB8?QtJU*Z)TVLHwylEG7CIF`op$h!9vB?btB`OUCWsdLqyzurnzQXte>< zS=l%kkRE^;kpTQ8(Jwjxp$tgQZLH=EKB@0c zDq?1EgZouI?3_3S-j^8AQ~yG#wbnhV9`z0}`%Vy)6Zwp~;DY*&(}p1cro^Y!uIJT5 zt`Qrj_sWWqjN6IiOcB}2rlHR5G0hwWFim8Z8)#7;M&SVvBVWPHU} zw5Uxh0|>}_X}Wk(0B{Z0P*L(E^G%J929N=VYXGoiI7+VOa*71tGrlAn+XH10u_`73 z_^?mw=fkEDHnQmS6F@#u2(0dw)68>*ELD~btYwg3<>xKwQwAJK-Wmr$4ZED6K;Tn8 zr7CUfSC#0W=PKa+KE2HhIyeAZ znTB-#7-yLv1Ob>KCnKkW%(9J=R#|$w*+GhBz^0Ud0*5JDIbaEZNXGy8h%)ApX>KO) zPT6P)z@{bdR~Xnr2}X*l9H;_E!h`?{U=Ky@ z@*S+_EFaVWF6Y|X-2kfyTuZegh>5V{i-@^zsWJUND87)Iuj)bHO;1$6@D&$SE!5Aw zsqGpu8*-;$Px3_s?u5D_0c>Y0i?v`4w=$KmSBp;0+CJJ%_{csdgZ7QWx6DhkMS<#`C|$QzTebA}sbsuoRPSt*AvJYgO{vvPqI%A?=7!|M8ULmh z34B-mQweMY2}4Dly|h_a1Z0|DQqWt>AY-1L{F@H3I$UWii3K~n(6|mRcmAPjbuh*;mKY4K^1msG z+M9pP>&7-;uZ-}q)+{KC&VO7pf%)18c!kG|t$IRF{j1aId}aLOBC8{sdo^{lCg!91 ztXZq9U(pAd_`LmfeWl1pdp?=?Gs)Zc`JklYesy7l7kcUie=DgaPiDLZP%&Y*s@&Gg zMBo?P#vH%qN^&CK@HQ{=8ZTk3(efLVrU0NkDJ-`kGvxe?Q=I2~y;~?6PuLc~0Eirx zoB(8mF`7+V02PR^^n0pw+5C9^l3bD>oqP*081{da%A5QE001R)MObuXVRU6WV{&C- zbY%cCFflPLFf%PNHdHY-IxsdmH83qOH##sdDXN4m0000bbVXQnWMOn=I&E)cX=Zr< zGB7bQEif}JF*Z~&HaajiIyEpYFgH3dFj)6IkpKVy8FWQhbW?9;ba!ELWdK2BZ(?O2 dNo`?gWm08fWO;GPWjp`?002ovPDHLkV1nHO+C=~W literal 0 HcmV?d00001 diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index dc921e60e388f..ab2bd3af32186 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2510,6 +2510,8 @@ + + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 7f0fc0b3e9c1d..8f8f32de7c28d 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -535,6 +535,11 @@ Access the SD card. + + Accessibility features + + Features that assistive technology can request. + @@ -934,6 +939,20 @@ Allows the holder to bind to the top-level interface of an accessibility service. Should never be needed for normal apps. + + request explore by touch + + Allows the hoder to request an + interaction mode in which touched items are spoken aloud and the UI can be explored + via gestures. + + + request enhanced web accessibility + + Allows the hoder to request + enabling of web accessibility enhancements. For example, installing scripts from + Google to make app content more accessible. + bind to a text service @@ -2695,25 +2714,6 @@ Voice search - - Enable Explore by Touch? - - - %1$s wants to enable Explore by Touch. - When Explore by Touch is turned on, you can hear or see descriptions of what\'s under - your finger or perform gestures to interact with the tablet. - - - %1$s wants to enable Explore by Touch. - When Explore by Touch is turned on, you can hear or see descriptions of what\'s under - your finger or perform gestures to interact with the phone. - 1 month ago diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index fc0ff559c5cc9..695c2aa708b85 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -71,7 +71,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 96; + private static final int DATABASE_VERSION = 97; private Context mContext; private int mUserHandle; @@ -1536,6 +1536,22 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 96; } + if (upgradeVersion == 96) { + // Remove Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + try { + db.execSQL("DELETE FROM system WHERE name='" + + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES + + "'"); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + upgradeVersion = 97; + } + // *** Remember to update DATABASE_VERSION above! if (upgradeVersion != currentVersion) { diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index b7c3450bcafd1..93187c1022ce9 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -23,15 +23,12 @@ import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; -import android.app.AlertDialog; import android.app.PendingIntent; import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; @@ -70,7 +67,6 @@ import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MagnificationSpec; -import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityManager; @@ -161,8 +157,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private Service mQueryBridge; - private AlertDialog mEnableTouchExplorationDialog; - private AccessibilityInputFilter mInputFilter; private boolean mHasInputFilter; @@ -250,12 +244,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { persistComponentNamesToSettingLocked( Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, state.mEnabledServices, userId); - // Update the touch exploration granted services setting. - state.mTouchExplorationGrantedServices.remove(comp); - persistComponentNamesToSettingLocked( - Settings.Secure. - TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, - state.mEnabledServices, userId); return; } } @@ -534,6 +522,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // No touch exploration. userState.mIsTouchExplorationEnabled = false; + // No touch enhanced web accessibility. + userState.mIsEnhancedWebAccessibilityEnabled = false; + // Hook the automation service up. mUiAutomationService = new Service(mCurrentUserId, componentName, accessibilityServiceInfo, true); @@ -559,16 +550,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { synchronized (mLock) { UserState userState = getCurrentUserStateLocked(); // Stash the old state so we can restore it when the keyguard is gone. - mTempStateChangeForCurrentUserMemento.initialize(mCurrentUserId, - getCurrentUserStateLocked()); + mTempStateChangeForCurrentUserMemento.initialize(getCurrentUserStateLocked()); // Set the temporary state. userState.mIsAccessibilityEnabled = true; - userState.mIsTouchExplorationEnabled= touchExplorationEnabled; + userState.mIsTouchExplorationEnabled = touchExplorationEnabled; + userState.mIsEnhancedWebAccessibilityEnabled = false; userState.mIsDisplayMagnificationEnabled = false; userState.mEnabledServices.clear(); userState.mEnabledServices.add(service); - userState.mTouchExplorationGrantedServices.clear(); - userState.mTouchExplorationGrantedServices.add(service); // Update the internal state. performServiceManagementLocked(userState); scheduleUpdateInputFilter(userState); @@ -842,14 +831,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { userState.mEnabledServices); } - private void populateTouchExplorationGrantedAccessibilityServicesLocked( - UserState userState) { - populateComponentNamesFromSettingLocked( - Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, - userState.mUserId, - userState.mTouchExplorationGrantedServices); - } - /** * Performs {@link AccessibilityService}s delayed notification. The delay is configurable * and denotes the period after the last event before notifying the service. @@ -896,6 +877,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { userState.mComponentNameToServiceMap.put(service.mComponentName, service); scheduleUpdateInputFilter(userState); tryEnableTouchExplorationLocked(service); + tryEnableEnhancedWebAccessibilityLocked(service); } catch (RemoteException e) { /* do nothing */ } @@ -918,6 +900,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { service.dispose(); scheduleUpdateInputFilter(userState); tryDisableTouchExplorationLocked(service); + tryDisableEnhancedWebAccessibilityLocked(service); return removed; } @@ -937,7 +920,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private boolean canDispathEventLocked(Service service, AccessibilityEvent event, int handledFeedbackTypes) { - if (!service.canReceiveEvents()) { + if (!service.canReceiveEventsLocked()) { return false; } @@ -1140,53 +1123,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private void showEnableTouchExplorationDialog(final Service service) { - String label = service.mResolveInfo.loadLabel( - mContext.getPackageManager()).toString(); - synchronized (mLock) { - final UserState state = getCurrentUserStateLocked(); - if (state.mIsTouchExplorationEnabled) { - return; - } - if (mEnableTouchExplorationDialog != null - && mEnableTouchExplorationDialog.isShowing()) { - return; - } - mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext) - .setIconAttribute(android.R.attr.alertDialogIcon) - .setPositiveButton(android.R.string.ok, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // The user allowed the service to toggle touch exploration. - state.mTouchExplorationGrantedServices.add(service.mComponentName); - persistComponentNamesToSettingLocked( - Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, - state.mTouchExplorationGrantedServices, state.mUserId); - // Enable touch exploration. - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, - service.mUserId); - } - }) - .setNegativeButton(android.R.string.cancel, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }) - .setTitle(R.string.enable_explore_by_touch_warning_title) - .setMessage(mContext.getString( - R.string.enable_explore_by_touch_warning_message, label)) - .create(); - mEnableTouchExplorationDialog.getWindow().setType( - WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags - |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; - mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true); - mEnableTouchExplorationDialog.show(); - } - } - private int getClientState(UserState userState) { int clientState = 0; if (userState.mIsAccessibilityEnabled) { @@ -1202,7 +1138,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void recreateInternalStateLocked(UserState userState) { populateInstalledAccessibilityServiceLocked(userState); populateEnabledAccessibilityServicesLocked(userState); - populateTouchExplorationGrantedAccessibilityServicesLocked(userState); handleTouchExplorationEnabledSettingChangedLocked(userState); handleDisplayMagnificationEnabledSettingChangedLocked(userState); @@ -1240,40 +1175,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 0, userState.mUserId) == 1; } - private void handleTouchExplorationGrantedAccessibilityServicesChangedLocked( - UserState userState) { - final int serviceCount = userState.mServices.size(); - for (int i = 0; i < serviceCount; i++) { - Service service = userState.mServices.get(i); - if (service.mRequestTouchExplorationMode - && userState.mTouchExplorationGrantedServices.contains( - service.mComponentName)) { - tryEnableTouchExplorationLocked(service); - return; - } + private void tryEnableTouchExplorationLocked(Service service) { + if (!service.mRequestTouchExplorationMode || !service.canReceiveEventsLocked()) { + return; } - if (userState.mIsTouchExplorationEnabled) { - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId); - } - } - - private void tryEnableTouchExplorationLocked(final Service service) { UserState userState = getUserStateLocked(service.mUserId); - if (!userState.mIsTouchExplorationEnabled && service.mRequestTouchExplorationMode - && service.canReceiveEvents()) { - final boolean canToggleTouchExploration = - userState.mTouchExplorationGrantedServices.contains(service.mComponentName); - if (!service.mIsAutomation && !canToggleTouchExploration) { - showEnableTouchExplorationDialog(service); - } else { - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId); - } + if (!userState.mIsTouchExplorationEnabled) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, userState.mUserId); } } private void tryDisableTouchExplorationLocked(Service service) { + if (!service.mRequestTouchExplorationMode) { + return; + } UserState userState = getUserStateLocked(service.mUserId); if (userState.mIsTouchExplorationEnabled) { final int serviceCount = userState.mServices.size(); @@ -1288,6 +1204,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + private void tryEnableEnhancedWebAccessibilityLocked(Service service) { + if (!service.mRequestEnhancedWebAccessibility || !service.canReceiveEventsLocked()) { + return; + } + UserState userState = getUserStateLocked(service.mUserId); + if (!userState.mIsEnhancedWebAccessibilityEnabled) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1, userState.mUserId); + } + } + + private void tryDisableEnhancedWebAccessibilityLocked(Service service) { + if (!service.mRequestEnhancedWebAccessibility) { + return; + } + UserState userState = getUserStateLocked(service.mUserId); + if (userState.mIsEnhancedWebAccessibilityEnabled) { + final int serviceCount = userState.mServices.size(); + for (int i = 0; i < serviceCount; i++) { + Service other = userState.mServices.get(i); + if (other != service && other.mRequestEnhancedWebAccessibility) { + return; + } + } + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0, userState.mUserId); + } + } + @Override public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); @@ -1494,6 +1439,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { boolean mRequestTouchExplorationMode; + boolean mRequestEnhancedWebAccessibility; + int mFetchFlags; long mNotificationTimeout; @@ -1547,9 +1494,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mIsAutomation = isAutomation; if (!isAutomation) { mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent(); - mRequestTouchExplorationMode = - (accessibilityServiceInfo.flags - & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; mIntent = new Intent().setComponent(mComponentName); mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, com.android.internal.R.string.accessibility_binding_label); @@ -1582,18 +1526,39 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0 ? AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS : 0; - mRequestTouchExplorationMode = (info.flags - & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; + if (mResolveInfo != null) { + String packageName = mResolveInfo.serviceInfo.packageName; + + if (mContext.getPackageManager().checkPermission( + android.Manifest.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE, + packageName) == PackageManager.PERMISSION_GRANTED) { + mRequestTouchExplorationMode = (info.flags + & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; + } + + if (mContext.getPackageManager().checkPermission( + android.Manifest.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY, + packageName) == PackageManager.PERMISSION_GRANTED) { + mRequestEnhancedWebAccessibility = (info.flags + & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0; + } + } // If this service is up and running we may have to enable touch - // exploration, otherwise this will happen when the service connects. + // exploration or enhanced web accessibility, otherwise this will + // happen when the service connects. synchronized (mLock) { - if (canReceiveEvents()) { + if (canReceiveEventsLocked()) { if (mRequestTouchExplorationMode) { tryEnableTouchExplorationLocked(this); } else { tryDisableTouchExplorationLocked(this); } + if (mRequestEnhancedWebAccessibility) { + tryEnableEnhancedWebAccessibilityLocked(this); + } else { + tryDisableEnhancedWebAccessibilityLocked(this); + } } } } @@ -1630,7 +1595,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } - public boolean canReceiveEvents() { + public boolean canReceiveEventsLocked() { return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); } @@ -2484,9 +2449,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public final Set mEnabledServices = new HashSet(); - public final Set mTouchExplorationGrantedServices = - new HashSet(); - public final SparseArray mInteractionConnections = new SparseArray(); @@ -2497,6 +2459,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public boolean mIsAccessibilityEnabled; public boolean mIsTouchExplorationEnabled; + public boolean mIsEnhancedWebAccessibilityEnabled; public boolean mIsDisplayMagnificationEnabled; public UserState(int userId) { @@ -2508,36 +2471,37 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public int mUserId = UserHandle.USER_NULL; public boolean mIsAccessibilityEnabled; public boolean mIsTouchExplorationEnabled; + public boolean mIsEnhancedWebAccessibilityEnabled; public boolean mIsDisplayMagnificationEnabled; public final Set mEnabledServices = new HashSet(); public final Set mTouchExplorationGrantedServices = new HashSet(); - public void initialize(int userId, UserState userState) { - mUserId = userId; + public void initialize(UserState userState) { + mUserId = userState.mUserId; mIsAccessibilityEnabled = userState.mIsAccessibilityEnabled; mIsTouchExplorationEnabled = userState.mIsTouchExplorationEnabled; + mIsEnhancedWebAccessibilityEnabled = userState.mIsEnhancedWebAccessibilityEnabled; mIsDisplayMagnificationEnabled = userState.mIsDisplayMagnificationEnabled; mEnabledServices.clear(); mEnabledServices.addAll(userState.mEnabledServices); mTouchExplorationGrantedServices.clear(); - mTouchExplorationGrantedServices.addAll(userState.mTouchExplorationGrantedServices); } public void applyTo(UserState userState) { userState.mIsAccessibilityEnabled = mIsAccessibilityEnabled; userState.mIsTouchExplorationEnabled = mIsTouchExplorationEnabled; + userState.mIsEnhancedWebAccessibilityEnabled = mIsEnhancedWebAccessibilityEnabled; userState.mIsDisplayMagnificationEnabled = mIsDisplayMagnificationEnabled; userState.mEnabledServices.clear(); userState.mEnabledServices.addAll(mEnabledServices); - userState.mTouchExplorationGrantedServices.clear(); - userState.mTouchExplorationGrantedServices.addAll(mTouchExplorationGrantedServices); } public void clear() { mUserId = UserHandle.USER_NULL; mIsAccessibilityEnabled = false; mIsTouchExplorationEnabled = false; + mIsEnhancedWebAccessibilityEnabled = false; mIsDisplayMagnificationEnabled = false; mEnabledServices.clear(); mTouchExplorationGrantedServices.clear(); @@ -2558,9 +2522,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor( Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); - private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure - .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); - public AccessibilityContentObserver(Handler handler) { super(handler); } @@ -2574,9 +2535,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri, false, this, UserHandle.USER_ALL); - contentResolver.registerContentObserver( - mTouchExplorationGrantedAccessibilityServicesUri, - false, this, UserHandle.USER_ALL); } @Override @@ -2621,15 +2579,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { manageServicesLocked(userState); } } - } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { - synchronized (mLock) { - // We will update when the automation service dies. - if (mUiAutomationService == null) { - UserState userState = getCurrentUserStateLocked(); - populateTouchExplorationGrantedAccessibilityServicesLocked(userState); - handleTouchExplorationGrantedAccessibilityServicesChangedLocked(userState); - } - } } } }