Fix bug 5237737 - ActionBar should fire an accessibility event when
action mode is turned on/off

Fire AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED when action modes
come and go to give an indication of UI change on the level of a menu
or dialog opening/closing.

Change-Id: Id36c6153b0722b4b6927c8d36503e8ac57c2d2b2
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index 25c0c99..220214b 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -16,6 +16,9 @@
 
 package android.inputmethodservice;
 
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPopupHelper;
+
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.ActionMode;
@@ -23,12 +26,10 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuPopupHelper;
-
 /**
  * ExtractEditLayout provides an ActionMode presentation for the
  * limited screen real estate in extract mode.
@@ -56,6 +57,7 @@
             mExtractActionButton.setVisibility(INVISIBLE);
             mEditButton.setVisibility(VISIBLE);
             mActionMode = mode;
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
             return mode;
         }
         return null;
@@ -158,6 +160,8 @@
             mExtractActionButton.setVisibility(VISIBLE);
             mEditButton.setVisibility(INVISIBLE);
 
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+
             mActionMode = null;
         }
 
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index ccca22e..afb5bf1 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -48,6 +48,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.Window;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.SpinnerAdapter;
 
 import java.lang.ref.WeakReference;
@@ -397,6 +398,7 @@
                 // TODO animate this
                 mSplitView.setVisibility(View.VISIBLE);
             }
+            mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
             mActionMode = mode;
             return mode;
         }
@@ -681,6 +683,7 @@
 
             // Clear out the context mode views after the animation finishes
             mContextView.closeMode();
+            mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
 
             mActionMode = null;
 
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index b54daba..ecda47e 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -26,6 +26,7 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 
 import java.lang.ref.WeakReference;
 
@@ -86,6 +87,7 @@
         }
         mFinished = true;
 
+        mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         mCallback.onDestroyActionMode(this);
     }
 
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index a631380..7bc33c7 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -34,6 +34,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -455,4 +456,17 @@
     public boolean shouldDelayChildPressedState() {
         return false;
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            // Action mode started
+            event.setSource(this);
+            event.setClassName(getClass().getName());
+            event.setPackageName(getContext().getPackageName());
+            event.setContentDescription(mTitle);
+        } else {
+            super.onInitializeAccessibilityEvent(event);
+        }
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 20088b1..903b405 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2171,6 +2171,8 @@
                         if (mActionModePopup != null) {
                             post(mShowActionModePopup);
                         }
+                        mActionModeView.sendAccessibilityEvent(
+                                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
                     } else {
                         mActionMode = null;
                     }