Bug 1019425 - Activate accessibility when both accessibilty and explore by touch are enabled. r=mfinkle
authorEitan Isaacson <eitan@monotonous.org>
Mon, 02 May 2016 14:02:16 -0700
changeset 296418 1f70bee0d12e24e17ad593a3735a93fa42f36a02
parent 296417 b54e9f0fb23ea28f6c21e414970f767f850d906f
child 296419 dba9974342da06718354291a6640d8e4b4b0c1f6
push id76321
push usereisaacson@mozilla.com
push dateFri, 06 May 2016 16:51:03 +0000
treeherdermozilla-inbound@1f70bee0d12e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs1019425
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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,24 +239,31 @@ 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() {
+    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);
+            }
+        });
+
+        if (Versions.feature19Plus) {
+            accessibilityManager.addTouchExplorationStateChangeListener(new AccessibilityManager.TouchExplorationStateChangeListener() {
                 @Override
-                public void onAccessibilityStateChanged(boolean enabled) {
+                public void onTouchExplorationStateChanged(boolean enabled) {
                     updateAccessibilitySettings(context);
                 }
             });
         }
     }
 
     public static void onLayerViewFocusChanged(LayerView layerview, boolean gainFocus) {
         if (sEnabled)
--- 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);