Bug 1019425 - Activate accessibility when both accessibilty and explore by touch are enabled. r?mfinkle draft
authorEitan Isaacson <eitan@monotonous.org>
Mon, 02 May 2016 14:02:16 -0700
changeset 363101 1f51d38aa4997a2f3c1545dfe0950f209e6949f5
parent 362943 0a25833062a880f369e6f9f622413a94cc671bf4
child 519936 08ec61a72149a8d8643f6e0682c1f0bfed80b38b
push id17097
push userbmo:eitan@monotonous.org
push dateTue, 03 May 2016 23:38:20 +0000
reviewersmfinkle
bugs1019425
milestone49.0a1
Bug 1019425 - Activate accessibility when both accessibilty and explore by touch are enabled. r?mfinkle This simplifies some old code. We get rid of a whitelist of services, and rely on the face that accessibility and explore by touch is enabled to enter our internal accessibility mode. The whitelist methode held 2 assumptions that are not true anymore: 1. There are some non-accessibility accessibility service apps in the wild that read notifications. In later Android versions this has been made into a non-a11y use case with NotificationListenerService. So the cases of non-a11y accessibility services has shrunk. 2. Not all screen readers (Gingerbread TalkBack, for example) supported explore by touch. Today, we exclusively support accessibility services that use explore by touch, and we should not activate our accessibility mode in any other case. MozReview-Commit-ID: LMeCedoIGbb
mobile/android/base/java/org/mozilla/gecko/GeckoAccessibility.java
mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoAccessibility.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoAccessibility.java
@@ -1,29 +1,23 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.UIAsyncTask;
 
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningServiceInfo;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -43,45 +37,27 @@ public class GeckoAccessibility {
     private static JSONObject sHoverEnter;
     private static AccessibilityNodeInfo sVirtualCursorNode;
     private static int sCurrentNode;
 
     // This is the number Brailleback uses to start indexing routing keys.
     private static final int BRAILLE_CLICK_BASE_INDEX = -275000000;
     private static SelfBrailleClient sSelfBrailleClient;
 
-    private static final HashSet<String> sServiceWhitelist =
-        new HashSet<String>(Arrays.asList(new String[] {
-                    "com.google.android.marvin.talkback.TalkBackService", // Google Talkback screen reader
-                    "com.mot.readout.ScreenReader", // Motorola screen reader
-                    "info.spielproject.spiel.SpielService", // Spiel screen reader
-                    "es.codefactory.android.app.ma.MAAccessibilityService" // Codefactory Mobile Accessibility screen reader
-                }));
-
     public static void updateAccessibilitySettings (final Context context) {
         new UIAsyncTask.WithoutParams<Void>(ThreadUtils.getBackgroundHandler()) {
                 @Override
                 public Void doInBackground() {
                     JSONObject ret = new JSONObject();
                     sEnabled = false;
                     AccessibilityManager accessibilityManager =
                         (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
-                    if (accessibilityManager.isEnabled()) {
-                        ActivityManager activityManager =
-                            (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-                        List<RunningServiceInfo> runningServices = activityManager.getRunningServices(Integer.MAX_VALUE);
-
-                        for (RunningServiceInfo runningServiceInfo : runningServices) {
-                            sEnabled = sServiceWhitelist.contains(runningServiceInfo.service.getClassName());
-                            if (sEnabled)
-                                break;
-                        }
-                        if (Versions.feature16Plus && sEnabled && sSelfBrailleClient == null) {
-                            sSelfBrailleClient = new SelfBrailleClient(GeckoAppShell.getContext(), false);
-                        }
+                    sEnabled = accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled();
+                    if (Versions.feature16Plus && sEnabled && sSelfBrailleClient == null) {
+                        sSelfBrailleClient = new SelfBrailleClient(GeckoAppShell.getContext(), false);
                     }
 
                     try {
                         ret.put("enabled", sEnabled);
                     } catch (Exception ex) {
                         Log.e(LOGTAG, "Error building JSON arguments for Accessibility:Settings:", ex);
                     }
 
@@ -263,28 +239,33 @@ public class GeckoAccessibility {
     public static void setDelegate(LayerView layerview) {
         // Only use this delegate in Jelly Bean.
         if (Versions.feature16Plus) {
             layerview.setAccessibilityDelegate(new GeckoAccessibilityDelegate());
             layerview.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
     }
 
-    public static void setAccessibilityStateChangeListener(final Context context) {
-        // The state change listener is only supported on API14+
-        if (Versions.feature14Plus) {
-            AccessibilityManager accessibilityManager =
-                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
-            accessibilityManager.addAccessibilityStateChangeListener(new AccessibilityManager.AccessibilityStateChangeListener() {
-                @Override
-                public void onAccessibilityStateChanged(boolean enabled) {
-                    updateAccessibilitySettings(context);
-                }
-            });
-        }
+    public static void setAccessibilityManagerListeners(final Context context) {
+        AccessibilityManager accessibilityManager =
+            (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+        accessibilityManager.addAccessibilityStateChangeListener(new AccessibilityManager.AccessibilityStateChangeListener() {
+            @Override
+            public void onAccessibilityStateChanged(boolean enabled) {
+                updateAccessibilitySettings(context);
+            }
+        });
+
+        accessibilityManager.addTouchExplorationStateChangeListener(new AccessibilityManager.TouchExplorationStateChangeListener() {
+            @Override
+            public void onTouchExplorationStateChanged(boolean enabled) {
+                updateAccessibilitySettings(context);
+            }
+        });
     }
 
     public static void onLayerViewFocusChanged(LayerView layerview, boolean gainFocus) {
         if (sEnabled)
             GeckoAppShell.notifyObservers("Accessibility:Focus", gainFocus ? "true" : "false");
     }
 
     public static class GeckoAccessibilityDelegate extends View.AccessibilityDelegate {
--- a/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java
@@ -127,17 +127,17 @@ public class LayerView extends ScrollVie
         mToolbarAnimator = mLayerClient.getDynamicToolbarAnimator();
 
         mRenderer = new LayerRenderer(this);
 
         setFocusable(true);
         setFocusableInTouchMode(true);
 
         GeckoAccessibility.setDelegate(this);
-        GeckoAccessibility.setAccessibilityStateChangeListener(getContext());
+        GeckoAccessibility.setAccessibilityManagerListeners(getContext());
     }
 
     /**
      * MotionEventHelper dragAsync() robocop tests can instruct
      * PanZoomController not to generate longpress events.
      */
     public void setIsLongpressEnabled(boolean isLongpressEnabled) {
         mPanZoomController.setIsLongpressEnabled(isLongpressEnabled);