Bring accessibility support lib up to date.

AccessibilityServiceInfoCompat, AccessibilityEventCompat, and
AccessibilityManagerCompat were all missing methods that were
added in previous released.

Bug: 28917702
Change-Id: Ia18d1969d3319d9c8e946d376f449d12a472a3ac
(cherry picked from commit 9c2c5a703a99ad0e29522e9dfc742ce393732e24)
diff --git a/api/current.txt b/api/current.txt
index cdfc5d5..51efae0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3629,10 +3629,11 @@
     method public static java.lang.String flagToString(int);
     method public static boolean getCanRetrieveWindowContent(android.accessibilityservice.AccessibilityServiceInfo);
     method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static java.lang.String getDescription(android.accessibilityservice.AccessibilityServiceInfo);
+    method public static deprecated java.lang.String getDescription(android.accessibilityservice.AccessibilityServiceInfo);
     method public static java.lang.String getId(android.accessibilityservice.AccessibilityServiceInfo);
     method public static android.content.pm.ResolveInfo getResolveInfo(android.accessibilityservice.AccessibilityServiceInfo);
     method public static java.lang.String getSettingsActivityName(android.accessibilityservice.AccessibilityServiceInfo);
+    method public static java.lang.String loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
     field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
     field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
@@ -6595,16 +6596,21 @@
   public final class AccessibilityEventCompat {
     method public static void appendRecord(android.view.accessibility.AccessibilityEvent, android.support.v4.view.accessibility.AccessibilityRecordCompat);
     method public static android.support.v4.view.accessibility.AccessibilityRecordCompat asRecord(android.view.accessibility.AccessibilityEvent);
+    method public int getAction(android.view.accessibility.AccessibilityEvent);
     method public static int getContentChangeTypes(android.view.accessibility.AccessibilityEvent);
+    method public int getMovementGranularity(android.view.accessibility.AccessibilityEvent);
     method public static android.support.v4.view.accessibility.AccessibilityRecordCompat getRecord(android.view.accessibility.AccessibilityEvent, int);
     method public static int getRecordCount(android.view.accessibility.AccessibilityEvent);
+    method public void setAction(android.view.accessibility.AccessibilityEvent, int);
     method public static void setContentChangeTypes(android.view.accessibility.AccessibilityEvent, int);
+    method public void setMovementGranularity(android.view.accessibility.AccessibilityEvent, int);
     field public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 4; // 0x4
     field public static final int CONTENT_CHANGE_TYPE_SUBTREE = 1; // 0x1
     field public static final int CONTENT_CHANGE_TYPE_TEXT = 2; // 0x2
     field public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int TYPES_ALL_MASK = -1; // 0xffffffff
     field public static final int TYPE_ANNOUNCEMENT = 16384; // 0x4000
+    field public static final int TYPE_ASSIST_READING_CONTEXT = 16777216; // 0x1000000
     field public static final int TYPE_GESTURE_DETECTION_END = 524288; // 0x80000
     field public static final int TYPE_GESTURE_DETECTION_START = 262144; // 0x40000
     field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
@@ -6613,20 +6619,24 @@
     field public static final int TYPE_TOUCH_INTERACTION_START = 1048576; // 0x100000
     field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
     field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
+    field public static final int TYPE_VIEW_CONTEXT_CLICKED = 8388608; // 0x800000
     field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
     field public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
     field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
     field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
     field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
+    field public static final int TYPE_WINDOWS_CHANGED = 4194304; // 0x400000
     field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
   }
 
   public final class AccessibilityManagerCompat {
     method public static boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager, android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener);
+    method public static boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, android.support.v4.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
     method public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(android.view.accessibility.AccessibilityManager, int);
     method public static java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(android.view.accessibility.AccessibilityManager);
     method public static boolean isTouchExplorationEnabled(android.view.accessibility.AccessibilityManager);
     method public static boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager, android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener);
+    method public static boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, android.support.v4.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener);
   }
 
   public static abstract interface AccessibilityManagerCompat.AccessibilityStateChangeListener {
@@ -6637,6 +6647,10 @@
     ctor public AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat();
   }
 
+  public static abstract interface AccessibilityManagerCompat.TouchExplorationStateChangeListener {
+    method public abstract void onTouchExplorationStateChanged(boolean);
+  }
+
   public class AccessibilityNodeInfoCompat {
     ctor public AccessibilityNodeInfoCompat(java.lang.Object);
     method public void addAction(int);
diff --git a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
index e9b50a0..9655197 100644
--- a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
+++ b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
@@ -18,6 +18,7 @@
 
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.view.View;
@@ -35,6 +36,7 @@
         public String getDescription(AccessibilityServiceInfo info);
         public String getSettingsActivityName(AccessibilityServiceInfo info);
         public int getCapabilities(AccessibilityServiceInfo info);
+        public String loadDescription(AccessibilityServiceInfo info, PackageManager pm);
     }
 
     static class AccessibilityServiceInfoStubImpl implements AccessibilityServiceInfoVersionImpl {
@@ -68,6 +70,11 @@
         public int getCapabilities(AccessibilityServiceInfo info) {
             return 0;
         }
+
+        @Override
+        public String loadDescription(AccessibilityServiceInfo info, PackageManager pm) {
+            return null;
+        }
     }
 
     static class AccessibilityServiceInfoIcsImpl extends AccessibilityServiceInfoStubImpl {
@@ -106,7 +113,15 @@
         }
     }
 
-    static class AccessibilityServiceInfoJellyBeanMr2 extends AccessibilityServiceInfoIcsImpl {
+    static class AccessibilityServiceInfoJellyBeanImpl extends AccessibilityServiceInfoIcsImpl {
+        @Override
+        public String loadDescription(AccessibilityServiceInfo info, PackageManager pm) {
+            return AccessibilityServiceInfoCompatJellyBean.loadDescription(info, pm);
+        }
+    }
+
+    static class AccessibilityServiceInfoJellyBeanMr2Impl
+            extends AccessibilityServiceInfoJellyBeanImpl {
         @Override
         public int getCapabilities(AccessibilityServiceInfo info) {
             return AccessibilityServiceInfoCompatJellyBeanMr2.getCapabilities(info);
@@ -115,7 +130,9 @@
 
     static {
         if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
-            IMPL = new AccessibilityServiceInfoJellyBeanMr2();
+            IMPL = new AccessibilityServiceInfoJellyBeanMr2Impl();
+        } else if (Build.VERSION.SDK_INT >= 16) { // JB
+            IMPL = new AccessibilityServiceInfoJellyBeanImpl();
         } else if (Build.VERSION.SDK_INT >= 14) { // ICS
             IMPL = new AccessibilityServiceInfoIcsImpl();
         } else {
@@ -291,6 +308,7 @@
      * <strong>Generated by the system.</strong>
      * </p>
      *
+     * @param info The service info of interest
      * @return The id.
      */
     public static String getId(AccessibilityServiceInfo info) {
@@ -303,6 +321,7 @@
      * <strong>Generated by the system.</strong>
      * </p>
      *
+     * @param info The service info of interest
      * @return The info.
      */
     public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) {
@@ -316,6 +335,7 @@
      * meta-data}.</strong>
      * </p>
      *
+     * @param info The service info of interest
      * @return The settings activity name.
      */
     public static String getSettingsActivityName(AccessibilityServiceInfo info) {
@@ -329,6 +349,7 @@
      * meta-data}.</strong>
      * </p>
      *
+     * @param info The service info of interest
      * @return True window content can be retrieved.
      */
     public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) {
@@ -336,19 +357,38 @@
     }
 
     /**
-     * Description of the accessibility service.
+     * Non-localized description of the accessibility service.
      * <p>
      * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
      * meta-data}.</strong>
      * </p>
      *
+     * @param info The service info of interest
      * @return The description.
+     *
+     * @deprecated Use {@link #loadDescription(AccessibilityServiceInfo, PackageManager)}.
      */
     public static String getDescription(AccessibilityServiceInfo info) {
         return IMPL.getDescription(info);
     }
 
     /**
+     * The localized description of the accessibility service.
+     * <p>
+     *    <strong>Statically set from
+     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+     * </p>
+     *
+     * @param info The service info of interest
+     * @param packageManager The current package manager
+     * @return The localized description.
+     */
+    public static String loadDescription(
+            AccessibilityServiceInfo info, PackageManager packageManager) {
+        return IMPL.loadDescription(info, packageManager);
+    }
+
+    /**
      * Returns the string representation of a feedback type. For example,
      * {@link AccessibilityServiceInfo#FEEDBACK_SPOKEN} is represented by the
      * string FEEDBACK_SPOKEN.
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java
index 7032f39..0941fe6 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityEventCompat.java
@@ -31,6 +31,10 @@
         Object getRecord(AccessibilityEvent event, int index);
         void setContentChangeTypes(AccessibilityEvent event, int types);
         int getContentChangeTypes(AccessibilityEvent event);
+        public void setMovementGranularity(AccessibilityEvent event, int granularity);
+        public int getMovementGranularity(AccessibilityEvent event);
+        public void setAction(AccessibilityEvent event, int action);
+        public int getAction(AccessibilityEvent event);
     }
 
     static class AccessibilityEventStubImpl implements AccessibilityEventVersionImpl {
@@ -59,6 +63,24 @@
         public int getContentChangeTypes(AccessibilityEvent event) {
             return 0;
         }
+
+        @Override
+        public void setMovementGranularity(AccessibilityEvent event, int granularity) {
+        }
+
+        @Override
+        public int getMovementGranularity(AccessibilityEvent event) {
+            return 0;
+        }
+
+        @Override
+        public void setAction(AccessibilityEvent event, int action) {
+        }
+
+        @Override
+        public int getAction(AccessibilityEvent event) {
+            return 0;
+        }
     }
 
     static class AccessibilityEventIcsImpl extends AccessibilityEventStubImpl {
@@ -79,7 +101,29 @@
         }
     }
 
-    static class AccessibilityEventKitKatImpl extends AccessibilityEventIcsImpl {
+    static class AccessibilityEventJellyBeanImpl extends AccessibilityEventIcsImpl {
+        @Override
+        public void setMovementGranularity(AccessibilityEvent event, int granularity) {
+            AccessibilityEventCompatJellyBean.setMovementGranularity(event, granularity);
+        }
+
+        @Override
+        public int getMovementGranularity(AccessibilityEvent event) {
+            return AccessibilityEventCompatJellyBean.getMovementGranularity(event);
+        }
+
+        @Override
+        public void setAction(AccessibilityEvent event, int action) {
+            AccessibilityEventCompatJellyBean.setAction(event, action);
+        }
+
+        @Override
+        public int getAction(AccessibilityEvent event) {
+            return AccessibilityEventCompatJellyBean.getAction(event);
+        }
+    }
+
+    static class AccessibilityEventKitKatImpl extends AccessibilityEventJellyBeanImpl {
 
         @Override
         public void setContentChangeTypes(AccessibilityEvent event, int types) {
@@ -97,6 +141,8 @@
     static {
         if (Build.VERSION.SDK_INT >= 19) { // KitKat
             IMPL = new AccessibilityEventKitKatImpl();
+        } else if (Build.VERSION.SDK_INT >= 16) { // Jellybean
+            IMPL = new AccessibilityEventJellyBeanImpl();
         } else if (Build.VERSION.SDK_INT >= 14) { // ICS
             IMPL = new AccessibilityEventIcsImpl();
         } else {
@@ -180,6 +226,21 @@
     public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
 
     /**
+     * Represents the event change in the windows shown on the screen.
+     */
+    public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
+
+    /**
+     * Represents the event of a context click on a {@link android.view.View}.
+     */
+    public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
+
+    /**
+     * Represents the event of the assistant currently reading the users screen context.
+     */
+    public static final int TYPE_ASSIST_READING_CONTEXT = 0x01000000;
+
+    /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * The type of change is not defined.
      */
@@ -313,4 +374,53 @@
         return IMPL.getContentChangeTypes(event);
     }
 
+    /**
+     * Sets the movement granularity that was traversed.
+     *
+     * @param granularity The granularity.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setMovementGranularity(AccessibilityEvent event, int granularity) {
+        IMPL.setMovementGranularity(event, granularity);
+    }
+
+    /**
+     * Gets the movement granularity that was traversed.
+     *
+     * @return The granularity.
+     */
+    public int getMovementGranularity(AccessibilityEvent event) {
+        return IMPL.getMovementGranularity(event);
+    }
+
+    /**
+     * Sets the performed action that triggered this event.
+     * <p>
+     * Valid actions are defined in {@link AccessibilityNodeInfoCompat}:
+     * <ul>
+     * <li>{@link AccessibilityNodeInfoCompat#ACTION_ACCESSIBILITY_FOCUS}
+     * <li>{@link AccessibilityNodeInfoCompat#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
+     * <li>{@link AccessibilityNodeInfoCompat#ACTION_CLEAR_FOCUS}
+     * <li>{@link AccessibilityNodeInfoCompat#ACTION_CLEAR_SELECTION}
+     * <li>{@link AccessibilityNodeInfoCompat#ACTION_CLICK}
+     * <li>etc.
+     * </ul>
+     *
+     * @param action The action.
+     * @throws IllegalStateException If called from an AccessibilityService.
+     * @see AccessibilityNodeInfoCompat#performAction(int)
+     */
+    public void setAction(AccessibilityEvent event, int action) {
+        IMPL.setAction(event, action);
+    }
+
+    /**
+     * Gets the performed action that triggered this event.
+     *
+     * @return The action.
+     */
+    public int getAction(AccessibilityEvent event) {
+        return IMPL.getAction(event);
+    }
 }
diff --git a/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java b/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java
index 3ced556..544091a 100644
--- a/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java
+++ b/compat/java/android/support/v4/view/accessibility/AccessibilityManagerCompat.java
@@ -20,6 +20,8 @@
 import android.os.Build;
 import android.support.v4.view.accessibility.AccessibilityManagerCompatIcs.AccessibilityStateChangeListenerBridge;
 import android.support.v4.view.accessibility.AccessibilityManagerCompatIcs.AccessibilityStateChangeListenerWrapper;
+import android.support.v4.view.accessibility.AccessibilityManagerCompatKitKat.TouchExplorationStateChangeListenerBridge;
+import android.support.v4.view.accessibility.AccessibilityManagerCompatKitKat.TouchExplorationStateChangeListenerWrapper;
 import android.view.accessibility.AccessibilityManager;
 
 import java.util.Collections;
@@ -32,7 +34,7 @@
 public final class AccessibilityManagerCompat {
 
     interface AccessibilityManagerVersionImpl {
-        AccessibilityStateChangeListenerWrapper newAccessiblityStateChangeListener(
+        AccessibilityStateChangeListenerWrapper newAccessibilityStateChangeListener(
                 AccessibilityStateChangeListener listener);
         boolean addAccessibilityStateChangeListener(AccessibilityManager manager,
                 AccessibilityStateChangeListener listener);
@@ -43,11 +45,17 @@
         List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(
                 AccessibilityManager manager);
         boolean isTouchExplorationEnabled(AccessibilityManager manager);
+        TouchExplorationStateChangeListenerWrapper newTouchExplorationStateChangeListener(
+                TouchExplorationStateChangeListener listener);
+        boolean addTouchExplorationStateChangeListener(AccessibilityManager manager,
+                TouchExplorationStateChangeListener listener);
+        boolean removeTouchExplorationStateChangeListener(AccessibilityManager manager,
+                TouchExplorationStateChangeListener listener);
     }
 
     static class AccessibilityManagerStubImpl implements AccessibilityManagerVersionImpl {
         @Override
-        public AccessibilityStateChangeListenerWrapper newAccessiblityStateChangeListener(
+        public AccessibilityStateChangeListenerWrapper newAccessibilityStateChangeListener(
                 AccessibilityStateChangeListener listener) {
             return null;
         }
@@ -80,11 +88,29 @@
         public boolean isTouchExplorationEnabled(AccessibilityManager manager) {
             return false;
         }
+
+        @Override
+        public TouchExplorationStateChangeListenerWrapper newTouchExplorationStateChangeListener(
+                TouchExplorationStateChangeListener listener) {
+            return null;
+        }
+
+        @Override
+        public boolean addTouchExplorationStateChangeListener(AccessibilityManager manager,
+                TouchExplorationStateChangeListener listener) {
+            return false;
+        }
+
+        @Override
+        public boolean removeTouchExplorationStateChangeListener(AccessibilityManager manager,
+                TouchExplorationStateChangeListener listener) {
+            return false;
+        }
     }
 
     static class AccessibilityManagerIcsImpl extends AccessibilityManagerStubImpl {
         @Override
-        public AccessibilityStateChangeListenerWrapper newAccessiblityStateChangeListener(
+        public AccessibilityStateChangeListenerWrapper newAccessibilityStateChangeListener(
                 final AccessibilityStateChangeListener listener) {
             return new AccessibilityStateChangeListenerWrapper(listener,
                     new AccessibilityStateChangeListenerBridge() {
@@ -99,14 +125,14 @@
         public boolean addAccessibilityStateChangeListener(AccessibilityManager manager,
                 AccessibilityStateChangeListener listener) {
             return AccessibilityManagerCompatIcs.addAccessibilityStateChangeListener(manager,
-                    newAccessiblityStateChangeListener(listener));
+                    newAccessibilityStateChangeListener(listener));
         }
 
         @Override
         public boolean removeAccessibilityStateChangeListener(AccessibilityManager manager,
                 AccessibilityStateChangeListener listener) {
             return AccessibilityManagerCompatIcs.removeAccessibilityStateChangeListener(manager,
-                    newAccessiblityStateChangeListener(listener));
+                    newAccessibilityStateChangeListener(listener));
         }
 
         @Override
@@ -128,8 +154,38 @@
         }
     }
 
+    static class AccessibilityManagerKitKatImpl extends AccessibilityManagerIcsImpl {
+        @Override
+        public TouchExplorationStateChangeListenerWrapper newTouchExplorationStateChangeListener(
+                final TouchExplorationStateChangeListener listener) {
+            return new TouchExplorationStateChangeListenerWrapper(listener,
+                    new TouchExplorationStateChangeListenerBridge() {
+                        @Override
+                        public void onTouchExplorationStateChanged(boolean enabled) {
+                            listener.onTouchExplorationStateChanged(enabled);
+                        }
+                    });
+        }
+
+        @Override
+        public boolean addTouchExplorationStateChangeListener(AccessibilityManager manager,
+                TouchExplorationStateChangeListener listener) {
+            return AccessibilityManagerCompatKitKat.addTouchExplorationStateChangeListener(
+                    manager, newTouchExplorationStateChangeListener(listener));
+        }
+
+        @Override
+        public boolean removeTouchExplorationStateChangeListener(AccessibilityManager manager,
+                TouchExplorationStateChangeListener listener) {
+            return AccessibilityManagerCompatKitKat.removeTouchExplorationStateChangeListener(
+                    manager, newTouchExplorationStateChangeListener(listener));
+        }
+    }
+
     static {
-        if (Build.VERSION.SDK_INT >= 14) { // ICS
+        if (Build.VERSION.SDK_INT >= 19) { // KitKat
+            IMPL = new AccessibilityManagerKitKatImpl();
+        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
             IMPL = new AccessibilityManagerIcsImpl();
         } else {
             IMPL = new AccessibilityManagerStubImpl();
@@ -204,6 +260,30 @@
     }
 
     /**
+     * Registers a {@link TouchExplorationStateChangeListener} for changes in
+     * the global touch exploration state of the system.
+     *
+     * @param listener The listener.
+     * @return True if successfully registered.
+     */
+    public static boolean addTouchExplorationStateChangeListener(AccessibilityManager manager,
+            TouchExplorationStateChangeListener listener) {
+        return IMPL.addTouchExplorationStateChangeListener(manager, listener);
+    }
+
+    /**
+     * Unregisters a {@link TouchExplorationStateChangeListener}.
+     *
+     * @param listener The listener.
+     * @return True if successfully unregistered.
+     */
+    public static boolean removeTouchExplorationStateChangeListener(AccessibilityManager manager,
+            TouchExplorationStateChangeListener listener) {
+        return IMPL.removeTouchExplorationStateChangeListener(manager, listener);
+    }
+
+    /**
+     * Listener for the accessibility state.
      * @deprecated Use {@link AccessibilityStateChangeListener} instead.
      */
     @Deprecated
@@ -223,5 +303,20 @@
         void onAccessibilityStateChanged(boolean enabled);
     }
 
+    /**
+     * Listener for the system touch exploration state. To listen for changes to
+     * the touch exploration state on the device, implement this interface and
+     * register it with the system by calling
+     * {@link #addTouchExplorationStateChangeListener}.
+     */
+    public interface TouchExplorationStateChangeListener {
+        /**
+         * Called when the touch exploration enabled state changes.
+         *
+         * @param enabled Whether touch exploration is enabled.
+         */
+        void onTouchExplorationStateChanged(boolean enabled);
+    }
+
     private AccessibilityManagerCompat() {}
 }
diff --git a/compat/jellybean/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatJellyBean.java b/compat/jellybean/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatJellyBean.java
new file mode 100644
index 0000000..f0f8d0c
--- /dev/null
+++ b/compat/jellybean/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompatJellyBean.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.accessibilityservice;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.pm.PackageManager;
+
+/**
+ * JB implementation of the new APIs in AccessibilityServiceInfo.
+ */
+class AccessibilityServiceInfoCompatJellyBean {
+
+    public static String loadDescription(AccessibilityServiceInfo info, PackageManager pm) {
+        return info.loadDescription(pm);
+    }
+}
diff --git a/compat/jellybean/android/support/v4/view/accessibility/AccessibilityEventCompatJellyBean.java b/compat/jellybean/android/support/v4/view/accessibility/AccessibilityEventCompatJellyBean.java
new file mode 100644
index 0000000..e557650
--- /dev/null
+++ b/compat/jellybean/android/support/v4/view/accessibility/AccessibilityEventCompatJellyBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.view.accessibility;
+
+import android.view.accessibility.AccessibilityEvent;
+
+class AccessibilityEventCompatJellyBean {
+    public static void setMovementGranularity(AccessibilityEvent event, int granularity) {
+        event.setMovementGranularity(granularity);
+    }
+
+    public static int getMovementGranularity(AccessibilityEvent event) {
+        return event.getMovementGranularity();
+    }
+
+    public static void setAction(AccessibilityEvent event, int action) {
+        event.setAction(action);
+    }
+
+    public static int getAction(AccessibilityEvent event) {
+        return event.getAction();
+    }
+}
diff --git a/compat/kitkat/android/support/v4/view/accessibility/AccessibilityManagerCompatKitKat.java b/compat/kitkat/android/support/v4/view/accessibility/AccessibilityManagerCompatKitKat.java
new file mode 100644
index 0000000..1cdedc0
--- /dev/null
+++ b/compat/kitkat/android/support/v4/view/accessibility/AccessibilityManagerCompatKitKat.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.view.accessibility;
+
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
+
+/**
+ * KitKat-specific AccessibilityManager API implementation.
+ */
+class AccessibilityManagerCompatKitKat {
+
+    public static class TouchExplorationStateChangeListenerWrapper
+            implements TouchExplorationStateChangeListener {
+        final Object mListener;
+        final TouchExplorationStateChangeListenerBridge mListenerBridge;
+
+        public TouchExplorationStateChangeListenerWrapper(Object listener,
+                TouchExplorationStateChangeListenerBridge listenerBridge) {
+            mListener = listener;
+            mListenerBridge = listenerBridge;
+        }
+
+        @Override
+        public int hashCode() {
+            return mListener == null ? 0 : mListener.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            TouchExplorationStateChangeListenerWrapper other =
+                    (TouchExplorationStateChangeListenerWrapper) o;
+            return mListener == null ? other.mListener == null : mListener.equals(other.mListener);
+        }
+
+        @Override
+        public void onTouchExplorationStateChanged(boolean enabled) {
+            mListenerBridge.onTouchExplorationStateChanged(enabled);
+        }
+    }
+
+    interface TouchExplorationStateChangeListenerBridge {
+        void onTouchExplorationStateChanged(boolean enabled);
+    }
+
+    public static Object newTouchExplorationStateChangeListener(
+            final TouchExplorationStateChangeListenerBridge bridge) {
+        return new TouchExplorationStateChangeListener() {
+            @Override
+            public void onTouchExplorationStateChanged(boolean enabled) {
+                bridge.onTouchExplorationStateChanged(enabled);
+            }
+        };
+    }
+
+    public static boolean addTouchExplorationStateChangeListener(AccessibilityManager manager,
+            Object listener) {
+        return manager.addTouchExplorationStateChangeListener(
+                (TouchExplorationStateChangeListener) listener);
+    }
+
+    public static boolean removeTouchExplorationStateChangeListener(AccessibilityManager manager,
+            Object listener) {
+        return manager.removeTouchExplorationStateChangeListener(
+                (TouchExplorationStateChangeListener) listener);
+    }
+}