1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.chrome.browser;
7 import android.accessibilityservice.AccessibilityServiceInfo;
8 import android.app.AlertDialog;
9 import android.content.Context;
10 import android.content.DialogInterface;
11 import android.content.Intent;
12 import android.content.pm.PackageInfo;
13 import android.content.pm.PackageManager;
14 import android.net.Uri;
15 import android.os.Build;
16 import android.view.accessibility.AccessibilityManager;
18 import org.chromium.base.CalledByNative;
19 import org.chromium.chrome.R;
21 import java.util.List;
24 * Exposes information about the current accessibility state
26 public class AccessibilityUtil {
27 // Whether we've already shown an alert that they have an old version of TalkBack running.
28 private static boolean sOldTalkBackVersionAlertShown = false;
30 // The link to download or update TalkBack from the Play Store.
31 private static final String TALKBACK_MARKET_LINK =
32 "market://search?q=pname:com.google.android.marvin.talkback";
34 // The package name for TalkBack, an Android accessibility service.
35 private static final String TALKBACK_PACKAGE_NAME =
36 "com.google.android.marvin.talkback";
38 // The minimum TalkBack version that we support. This is the version that shipped with
39 // KitKat, from fall 2013. Versions older than that should be updated.
40 private static final int MIN_TALKBACK_VERSION = 105;
42 private AccessibilityUtil() { }
45 * Checks to see that this device has accessibility and touch exploration enabled.
46 * @param context A {@link Context} instance.
47 * @return Whether or not accessibility and touch exploration are enabled.
50 public static boolean isAccessibilityEnabled(Context context) {
51 AccessibilityManager manager = (AccessibilityManager)
52 context.getSystemService(Context.ACCESSIBILITY_SERVICE);
53 return manager != null && manager.isEnabled() && manager.isTouchExplorationEnabled();
57 * Checks to see if an old version of TalkBack is running that Chrome doesn't support,
58 * and if so, shows an alert dialog prompting the user to update the app.
59 * @param context A {@link Context} instance.
60 * @return True if the dialog was shown.
62 public static boolean showWarningIfOldTalkbackRunning(Context context) {
63 AccessibilityManager manager = (AccessibilityManager)
64 context.getSystemService(Context.ACCESSIBILITY_SERVICE);
65 if (manager == null) return false;
67 boolean isTalkbackRunning = false;
69 List<AccessibilityServiceInfo> services =
70 manager.getEnabledAccessibilityServiceList(
71 AccessibilityServiceInfo.FEEDBACK_SPOKEN);
72 for (AccessibilityServiceInfo service : services) {
73 if (service.getId().contains(TALKBACK_PACKAGE_NAME)) isTalkbackRunning = true;
75 } catch (NullPointerException e) {
76 // getEnabledAccessibilityServiceList() can throw an NPE due to a bad
77 // AccessibilityService.
79 if (!isTalkbackRunning) return false;
82 PackageInfo talkbackInfo = context.getPackageManager().getPackageInfo(
83 TALKBACK_PACKAGE_NAME, 0);
84 if (talkbackInfo != null && talkbackInfo.versionCode < MIN_TALKBACK_VERSION &&
85 Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN &&
86 !sOldTalkBackVersionAlertShown) {
87 showOldTalkbackVersionAlertOnce(context);
90 } catch (PackageManager.NameNotFoundException e) {
91 // Do nothing, default to false.
97 private static void showOldTalkbackVersionAlertOnce(final Context context) {
98 if (sOldTalkBackVersionAlertShown) return;
99 sOldTalkBackVersionAlertShown = true;
101 AlertDialog.Builder builder = new AlertDialog.Builder(context)
102 .setTitle(R.string.old_talkback_title)
103 .setPositiveButton(R.string.update_from_market,
104 new DialogInterface.OnClickListener() {
106 public void onClick(DialogInterface dialog, int id) {
107 Uri marketUri = Uri.parse(TALKBACK_MARKET_LINK);
108 Intent marketIntent = new Intent(
109 Intent.ACTION_VIEW, marketUri);
110 context.startActivity(marketIntent);
113 .setNegativeButton(R.string.cancel_talkback_alert,
114 new DialogInterface.OnClickListener() {
116 public void onClick(DialogInterface dialog, int id) {
117 // Do nothing, this alert is only shown once either way.
120 AlertDialog dialog = builder.create();