From 5f312c9c1546da9f73d02f911d3365da4ff658fb Mon Sep 17 00:00:00 2001
From: alanv <alanv@google.com>
Date: Fri, 10 Aug 2012 13:51:17 -0700
Subject: [PATCH] Change accessibility event type for app-driven speech.

Bug: 6614400
Change-Id: I0ef309b7f3f35bf37b4664ea599c9e6ffb1a4ab8
---
 .../accessibility/AccessibilityUtils.java     | 33 +++++++++++++++----
 .../AccessibleKeyboardViewProxy.java          |  4 +--
 .../android/inputmethod/latin/LatinIME.java   |  2 +-
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 616b1c6d7..58d3022c9 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -19,10 +19,15 @@ package com.android.inputmethod.accessibility;
 import android.content.Context;
 import android.inputmethodservice.InputMethodService;
 import android.media.AudioManager;
+import android.os.Build;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.util.Log;
 import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.EditorInfo;
@@ -138,9 +143,10 @@ public class AccessibilityUtils {
      * Sends the specified text to the {@link AccessibilityManager} to be
      * spoken.
      *
-     * @param text the text to speak
+     * @param view The source view.
+     * @param text The text to speak.
      */
-    public void speak(CharSequence text) {
+    public void announceForAccessibility(View view, CharSequence text) {
         if (!mAccessibilityManager.isEnabled()) {
             Log.e(TAG, "Attempted to speak when accessibility was disabled!");
             return;
@@ -149,8 +155,7 @@ public class AccessibilityUtils {
         // The following is a hack to avoid using the heavy-weight TextToSpeech
         // class. Instead, we're just forcing a fake AccessibilityEvent into
         // the screen reader to make it speak.
-        final AccessibilityEvent event = AccessibilityEvent
-                .obtain(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        final AccessibilityEvent event = AccessibilityEvent.obtain();
 
         event.setPackageName(PACKAGE);
         event.setClassName(CLASS);
@@ -158,20 +163,34 @@ public class AccessibilityUtils {
         event.setEnabled(true);
         event.getText().add(text);
 
-        mAccessibilityManager.sendAccessibilityEvent(event);
+        // Platforms starting at SDK 16 should use announce events.
+        if (Build.VERSION.SDK_INT >= 16) {
+            event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
+        } else {
+            event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        }
+
+        final ViewParent viewParent = view.getParent();
+        if ((viewParent == null) || !(viewParent instanceof ViewGroup)) {
+            Log.e(TAG, "Failed to obtain ViewParent in announceForAccessibility");
+            return;
+        }
+
+        viewParent.requestSendAccessibilityEvent(view, event);
     }
 
     /**
      * Handles speaking the "connect a headset to hear passwords" notification
      * when connecting to a password field.
      *
+     * @param view The source view.
      * @param editorInfo The input connection's editor info attribute.
      * @param restarting Whether the connection is being restarted.
      */
-    public void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+    public void onStartInputViewInternal(View view, EditorInfo editorInfo, boolean restarting) {
         if (shouldObscureInput(editorInfo)) {
             final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
-            speak(text);
+            announceForAccessibility(view, text);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 4ecbf827a..2fff73154 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -250,7 +250,7 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat {
             text = context.getText(R.string.spoken_description_shiftmode_off);
         }
 
-        AccessibilityUtils.getInstance().speak(text);
+        AccessibilityUtils.getInstance().announceForAccessibility(mView, text);
     }
 
     /**
@@ -290,6 +290,6 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat {
         }
 
         final String text = context.getString(resId);
-        AccessibilityUtils.getInstance().speak(text);
+        AccessibilityUtils.getInstance().announceForAccessibility(mView, text);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 455086015..25cddb22d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -663,7 +663,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         // Forward this event to the accessibility utilities, if enabled.
         final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
         if (accessUtils.isTouchExplorationEnabled()) {
-            accessUtils.onStartInputViewInternal(editorInfo, restarting);
+            accessUtils.onStartInputViewInternal(inputView, editorInfo, restarting);
         }
 
         if (!restarting) {