Accessibility feature - framework changes (replacing 698, 699, 700, 701 and merging with the latest Donut)
diff --git a/Android.mk b/Android.mk
index ca76fb4..bbda5fb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -64,6 +64,8 @@
 ##
 ## READ ME: ########################################################
 LOCAL_SRC_FILES += \
+	core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
+  core/java/android/accessibilityservice/IEventListener.aidl \
 	core/java/android/accounts/IAccountsService.aidl \
 	core/java/android/app/IActivityPendingResult.aidl \
 	core/java/android/app/IActivityWatcher.aidl \
@@ -106,6 +108,8 @@
 	core/java/android/os/IPermissionController.aidl \
 	core/java/android/os/IPowerManager.aidl \
 	core/java/android/text/IClipboard.aidl \
+	core/java/android/view/accessibility/IAccessibilityManager.aidl \
+	core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
 	core/java/android/view/IApplicationToken.aidl \
 	core/java/android/view/IOnKeyguardExitResult.aidl \
 	core/java/android/view/IRotationWatcher.aidl \
diff --git a/api/current.xml b/api/current.xml
index eaf1512..c03526d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2550,6 +2550,17 @@
  visibility="public"
 >
 </field>
+<field name="contentDescription"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843379"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="cropToPadding"
  type="int"
  transient="false"
@@ -12656,6 +12667,270 @@
 </constructor>
 </class>
 </package>
+<package name="android.accessibilityservice"
+>
+<class name="AccessibilityService"
+ extends="android.app.Service"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AccessibilityService"
+ type="android.accessibilityservice.AccessibilityService"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onAccessibilityEvent"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
+<method name="onBind"
+ return="android.os.IBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onInterrupt"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onServiceConnected"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="setServiceInfo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="info" type="android.accessibilityservice.AccessibilityServiceInfo">
+</parameter>
+</method>
+<field name="SERVICE_INTERFACE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.accessibilityservice.AccessibilityService&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="AccessibilityServiceInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="AccessibilityServiceInfo"
+ type="android.accessibilityservice.AccessibilityServiceInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEEDBACK_AUDIBLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEEDBACK_GENERIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEEDBACK_HAPTIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEEDBACK_SPOKEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEEDBACK_VISUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="eventTypes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="feedbackType"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="flags"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="notificationTimeout"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="packageNames"
+ type="java.lang.String[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
 <package name="android.app"
 >
 <class name="Activity"
@@ -12764,6 +13039,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchPopulateAccessibilityEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
 <method name="dispatchTouchEvent"
  return="boolean"
  abstract="false"
@@ -16759,6 +17047,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchPopulateAccessibilityEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
 <method name="dispatchTouchEvent"
  return="boolean"
  abstract="false"
@@ -24974,6 +25275,17 @@
 <parameter name="receiver" type="android.content.BroadcastReceiver">
 </parameter>
 </method>
+<field name="ACCESSIBILITY_SERVICE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessibility&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTIVITY_SERVICE"
  type="java.lang.String"
  transient="false"
@@ -101868,6 +102180,17 @@
 <parameter name="value" type="java.lang.String">
 </parameter>
 </method>
+<field name="ACCESSIBILITY_ENABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessibility_enabled&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ADB_ENABLED"
  type="java.lang.String"
  transient="false"
@@ -101966,6 +102289,17 @@
  visibility="public"
 >
 </field>
+<field name="ENABLED_ACCESSIBILITY_SERVICES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;enabled_accessibility_services&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ENABLED_INPUT_METHODS"
  type="java.lang.String"
  transient="false"
@@ -134575,6 +134909,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.view.accessibility.AccessibilityEventSource">
+</implements>
 <implements name="android.graphics.drawable.Drawable.Callback">
 </implements>
 <implements name="android.view.KeyEvent.Callback">
@@ -134630,6 +134966,23 @@
 <parameter name="direction" type="int">
 </parameter>
 </method>
+<method name="addFocusables"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="views" type="java.util.ArrayList&lt;android.view.View&gt;">
+</parameter>
+<parameter name="direction" type="int">
+</parameter>
+<parameter name="focusableMode" type="int">
+</parameter>
+</method>
 <method name="addTouchables"
  return="void"
  abstract="false"
@@ -134864,6 +135217,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchPopulateAccessibilityEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
 <method name="dispatchRestoreInstanceState"
  return="void"
  abstract="false"
@@ -135158,6 +135524,17 @@
  visibility="protected"
 >
 </method>
+<method name="getContentDescription"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getContext"
  return="android.content.Context"
  abstract="false"
@@ -137114,6 +137491,32 @@
 <parameter name="y" type="int">
 </parameter>
 </method>
+<method name="sendAccessibilityEvent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventType" type="int">
+</parameter>
+</method>
+<method name="sendAccessibilityEventUnchecked"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
 <method name="setAnimation"
  return="void"
  abstract="false"
@@ -137179,6 +137582,19 @@
 <parameter name="clickable" type="boolean">
 </parameter>
 </method>
+<method name="setContentDescription"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="contentDescription" type="java.lang.CharSequence">
+</parameter>
+</method>
 <method name="setDrawingCacheBackgroundColor"
  return="void"
  abstract="false"
@@ -137967,6 +138383,28 @@
  visibility="protected"
 >
 </field>
+<field name="FOCUSABLES_ALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FOCUSABLES_TOUCH_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FOCUSED_SELECTED_STATE_SET"
  type="int[]"
  transient="false"
@@ -142659,6 +143097,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchPopulateAccessibilityEvent"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
 <method name="dispatchTouchEvent"
  return="boolean"
  abstract="true"
@@ -144083,6 +144534,698 @@
 </field>
 </class>
 </package>
+<package name="android.view.accessibility"
+>
+<class name="AccessibilityEvent"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAddedCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBeforeText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getClassName"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getContentDescription"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentItemIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEventTime"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEventType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFromIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getItemCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPackageName"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getParcelableData"
+ return="android.os.Parcelable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRemovedCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getText"
+ return="java.util.List&lt;java.lang.CharSequence&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initFromParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+</method>
+<method name="isChecked"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isFullScreen"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isPassword"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="obtain"
+ return="android.view.accessibility.AccessibilityEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventType" type="int">
+</parameter>
+</method>
+<method name="obtain"
+ return="android.view.accessibility.AccessibilityEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="recycle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAddedCount"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="addedCount" type="int">
+</parameter>
+</method>
+<method name="setBeforeText"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="beforeText" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setChecked"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isChecked" type="boolean">
+</parameter>
+</method>
+<method name="setClassName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="className" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setContentDescription"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="contentDescription" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setCurrentItemIndex"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="currentItemIndex" type="int">
+</parameter>
+</method>
+<method name="setEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isEnabled" type="boolean">
+</parameter>
+</method>
+<method name="setEventTime"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventTime" type="long">
+</parameter>
+</method>
+<method name="setEventType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventType" type="int">
+</parameter>
+</method>
+<method name="setFromIndex"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromIndex" type="int">
+</parameter>
+</method>
+<method name="setFullScreen"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isFullScreen" type="boolean">
+</parameter>
+</method>
+<method name="setItemCount"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="itemCount" type="int">
+</parameter>
+</method>
+<method name="setPackageName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setParcelableData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcelableData" type="android.os.Parcelable">
+</parameter>
+</method>
+<method name="setPassword"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isPassword" type="boolean">
+</parameter>
+</method>
+<method name="setRemovedCount"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="removedCount" type="int">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INVALID_POSITION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_TEXT_LENGTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="500"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPES_ALL_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_NOTIFICATION_STATE_CHANGED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="64"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_VIEW_CLICKED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_VIEW_FOCUSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_VIEW_LONG_CLICKED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_VIEW_SELECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_VIEW_TEXT_CHANGED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_WINDOW_STATE_CHANGED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="AccessibilityEventSource"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="sendAccessibilityEvent"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventType" type="int">
+</parameter>
+</method>
+<method name="sendAccessibilityEventUnchecked"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
+</interface>
+<class name="AccessibilityManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAccessibilityServiceList"
+ return="java.util.List&lt;android.content.pm.ServiceInfo&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="interrupt"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="sendAccessibilityEvent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
+</parameter>
+</method>
+</class>
+</package>
 <package name="android.view.animation"
 >
 <class name="AccelerateDecelerateInterpolator"
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
new file mode 100644
index 0000000..a3456c7
--- /dev/null
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2009 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.accessibilityservice;
+
+import com.android.internal.os.HandlerCaller;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * An accessibility service runs in the background and receives callbacks by the system
+ * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
+ * in the user interface, for example, the focus has changed, a button has been clicked,
+ * etc.
+ * <p>
+ * An accessibility service extends this class and implements its abstract methods. Such
+ * a service is declared as any other service in an AndroidManifest.xml but it must also
+ * specify that it handles the "android.accessibilityservice.AccessibilityService"
+ * {@link android.content.Intent}. Following is an example of such a declaration:
+ * <p>
+ * <code>
+ * &lt;service android:name=".MyAccessibilityService"&gt;<br>
+ *     &lt;intent-filter&gt;<br>
+ *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;<br>
+ *     &lt;/intent-filter&gt;<br>
+ * &lt;/service&gt;<br>
+ * </code>
+ * <p>
+ * The lifecycle of an accessibility service is managed exclusively by the system. Starting
+ * or stopping an accessibility service is triggered by an explicit user action through
+ * enabling or disabling it in the device settings. After the system binds to a service it
+ * calls {@link AccessibilityService#onServiceConnected()}. This method can be
+ * overriden by clients that want to perform post binding setup. An accessibility service
+ * is configured though setting an {@link AccessibilityServiceInfo} by calling
+ * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. You can call this
+ * method any time to change the service configuration but it is good practice to do that
+ * in the overriden {@link AccessibilityService#onServiceConnected()}.
+ * <p>
+ * An accessibility service can be registered for events in specific packages to provide a
+ * specific type of feedback and is notified with a certain timeout after the last event
+ * of interest has been fired.
+ * <p>
+ * <b>Notification strategy</b>
+ * <p>
+ * For each feedback type only one accessibility service is notified. Services are notified
+ * in the order of registration. Hence, if two services are registered for the same
+ * feedback type in the same package the first one wins. It is possible however, to
+ * register a service as the default one for a given feedback type. In such a case this
+ * service is invoked if no other service was interested in the event. In other words, default
+ * services do not compete with other services and are notified last regardless of the
+ * registration order. This enables "generic" accessibility services that work reasonably
+ * well with most applications to coexist with "polished" ones that are targeted for
+ * specific applications.
+ * <p>
+ * <b>Event types</b>
+ * <p>
+ * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}
+ * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
+ * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
+ * {@link AccessibilityEvent#TYPE_VIEW_SELECTED}
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
+ * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
+ * {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}
+ *  <p>
+ *  <b>Feedback types</b>
+ *  <p>
+ * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
+ * {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
+ * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
+ * {@link AccessibilityServiceInfo#FEEDBACK_VISUAL}
+ * {@link AccessibilityServiceInfo#FEEDBACK_GENERIC}
+ *
+ * @see AccessibilityEvent
+ * @see AccessibilityServiceInfo
+ * @see android.view.accessibility.AccessibilityManager
+ *
+ * Note: The event notification timeout is useful to avoid propagating events to the client
+ *       too frequently since this is accomplished via an expensive interprocess call.
+ *       One can think of the timeout as a criteria to determine when event generation has
+ *       settled down.
+ */
+public abstract class AccessibilityService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    public static final String SERVICE_INTERFACE =
+        "android.accessibilityservice.AccessibilityService";
+
+    private static final String LOG_TAG = "AccessibilityService";
+
+    private AccessibilityServiceInfo mInfo;
+
+    IAccessibilityServiceConnection mConnection;
+
+    /**
+     * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
+     *
+     * @param event An event.
+     */
+    public abstract void onAccessibilityEvent(AccessibilityEvent event);
+
+    /**
+     * Callback for interrupting the accessibility feedback.
+     */
+    public abstract void onInterrupt();
+
+    /**
+     * This method is a part of the {@link AccessibilityService} lifecycle and is
+     * called after the system has successfully bound to the service. If is
+     * convenient to use this method for setting the {@link AccessibilityServiceInfo}.
+     *
+     * @see AccessibilityServiceInfo
+     * @see #setServiceInfo(AccessibilityServiceInfo)
+     */
+    protected void onServiceConnected() {
+
+    }
+
+    /**
+     * Sets the {@link AccessibilityServiceInfo} that describes this service.
+     * <p>
+     * Note: You can call this method any time but the info will be picked up after
+     *       the system has bound to this service and when this method is called thereafter.
+     *
+     * @param info The info.
+     */
+    public final void setServiceInfo(AccessibilityServiceInfo info) {
+        mInfo = info;
+        sendServiceInfo();
+    }
+
+    /**
+     * Sets the {@link AccessibilityServiceInfo} for this service if the latter is
+     * properly set and there is an {@link IAccessibilityServiceConnection} to the
+     * AccessibilityManagerService.
+     */
+    private void sendServiceInfo() {
+        if (mInfo != null && mConnection != null) {
+            try {
+                mConnection.setServiceInfo(mInfo);
+            } catch (RemoteException re) {
+                Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
+            }
+        }
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        return new IEventListenerWrapper(this);
+    }
+
+    /**
+     * Implements the internal {@link IEventListener} interface to convert
+     * incoming calls to it back to calls on an {@link AccessibilityService}.
+     */
+    class IEventListenerWrapper extends IEventListener.Stub
+            implements HandlerCaller.Callback {
+
+        private static final int DO_SET_SET_CONNECTION = 10;
+        private static final int DO_ON_INTERRUPT = 20;
+        private static final int DO_ON_ACCESSIBILITY_EVENT = 30;
+
+        private final HandlerCaller mCaller;
+
+        private AccessibilityService mTarget;
+
+        public IEventListenerWrapper(AccessibilityService context) {
+            mTarget = context;
+            mCaller = new HandlerCaller(context, this);
+        }
+
+        public void setConnection(IAccessibilityServiceConnection connection) {
+            Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection);
+            mCaller.sendMessage(message);
+        }
+
+        public void onInterrupt() {
+            Message message = mCaller.obtainMessage(DO_ON_INTERRUPT);
+            mCaller.sendMessage(message);
+        }
+
+        public void onAccessibilityEvent(AccessibilityEvent event) {
+            Message message = mCaller.obtainMessageO(DO_ON_ACCESSIBILITY_EVENT, event);
+            mCaller.sendMessage(message);
+        }
+
+        public void executeMessage(Message message) {
+            switch (message.what) {
+                case DO_ON_ACCESSIBILITY_EVENT :
+                    AccessibilityEvent event = (AccessibilityEvent) message.obj;
+                    mTarget.onAccessibilityEvent(event);
+                    event.recycle();
+                    return;
+                case DO_ON_INTERRUPT :
+                    mTarget.onInterrupt();
+                    return;
+                case DO_SET_SET_CONNECTION :
+                    mConnection = ((IAccessibilityServiceConnection) message.obj);
+                    mTarget.onServiceConnected();
+                    return;
+                default :
+                    Log.w(LOG_TAG, "Unknown message type " + message.what);
+            }
+        }
+    }
+}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl b/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl
new file mode 100644
index 0000000..1f5d385
--- /dev/null
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2009 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.accessibilityservice;
+
+parcelable AccessibilityServiceInfo;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
new file mode 100644
index 0000000..4761f98
--- /dev/null
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2009 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.accessibilityservice;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class describes an {@link AccessibilityService}. The system
+ * notifies an {@link AccessibilityService} for
+ * {@link android.view.accessibility.AccessibilityEvent}s
+ * according to the information encapsulated in this class.
+ *
+ * @see AccessibilityService
+ * @see android.view.accessibility.AccessibilityEvent
+ */
+public class AccessibilityServiceInfo implements Parcelable {
+
+    /**
+     * Denotes spoken feedback.
+     */
+    public static final int FEEDBACK_SPOKEN = 0x0000001;
+
+    /**
+     * Denotes haptic feedback.
+     */
+    public static final int FEEDBACK_HAPTIC =  0x0000002;
+
+    /**
+     * Denotes audible (not spoken) feedback.
+     */
+    public static final int FEEDBACK_AUDIBLE = 0x0000004;
+
+    /**
+     * Denotes visual feedback.
+     */
+    public static final int FEEDBACK_VISUAL = 0x0000008;
+
+    /**
+     * Denotes generic feedback.
+     */
+    public static final int FEEDBACK_GENERIC = 0x0000010;
+
+    /**
+     * If an {@link AccessibilityService} is the default for a given type.
+     * Default service is invoked only if no package specific one exists. In case of
+     * more than one package specific service only the earlier registered is notified.
+     */
+    public static final int DEFAULT = 0x0000001;
+
+    /**
+     * The event types an {@link AccessibilityService} is interested in.
+     *
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_ACTIVITY_STARTED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
+     */
+    public int eventTypes;
+
+    /**
+     * The package names an {@link AccessibilityService} is interested in. Setting
+     * to null is equivalent to all packages. 
+     */
+    public String[] packageNames;
+
+    /**
+     * The feedback type an {@link AccessibilityService} provides.
+     *
+     * @see #FEEDBACK_AUDIBLE
+     * @see #FEEDBACK_GENERIC
+     * @see #FEEDBACK_HAPTIC
+     * @see #FEEDBACK_SPOKEN
+     * @see #FEEDBACK_VISUAL
+     */
+    public int feedbackType;
+
+    /**
+     * The timeout after the most recent event of a given type before an
+     * {@link AccessibilityService} is notified.
+     * <p>
+     * Note: The event notification timeout is useful to avoid propagating events to the client
+     *       too frequently since this is accomplished via an expensive interprocess call.
+     *       One can think of the timeout as a criteria to determine when event generation has
+     *       settled down
+     */
+    public long notificationTimeout;
+
+    /**
+     * This field represents a set of flags used for configuring an
+     * {@link AccessibilityService}.
+     *
+     * @see #DEFAULT
+     */
+    public int flags;
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(eventTypes);
+        parcel.writeStringArray(packageNames);
+        parcel.writeInt(feedbackType);
+        parcel.writeLong(notificationTimeout);
+        parcel.writeInt(flags);
+    }
+
+    /**
+     * @see Parcelable.Creator
+     */
+    public static final Parcelable.Creator<AccessibilityServiceInfo> CREATOR =
+            new Parcelable.Creator<AccessibilityServiceInfo>() {
+        public AccessibilityServiceInfo createFromParcel(Parcel parcel) {
+            AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+            info.eventTypes = parcel.readInt();
+            info.packageNames = parcel.readStringArray();
+            info.feedbackType = parcel.readInt();
+            info.notificationTimeout = parcel.readLong();
+            info.flags = parcel.readInt();
+            return info;
+        }
+
+        public AccessibilityServiceInfo[] newArray(int size) {
+            return new AccessibilityServiceInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
new file mode 100644
index 0000000..7157def
--- /dev/null
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 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.accessibilityservice;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+
+/**
+ * Interface AccessibilityManagerService#Service implements, and passes to an
+ * AccessibilityService so it can dynamically configure how the system handles it.
+ *
+ * @hide
+ */
+oneway interface IAccessibilityServiceConnection {
+
+    void setServiceInfo(in AccessibilityServiceInfo info);
+}
diff --git a/core/java/android/accessibilityservice/IEventListener.aidl b/core/java/android/accessibilityservice/IEventListener.aidl
new file mode 100644
index 0000000..5b849f1
--- /dev/null
+++ b/core/java/android/accessibilityservice/IEventListener.aidl
@@ -0,0 +1,34 @@
+/*
+** Copyright 2009, 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.accessibilityservice;
+
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * Top-level interface to accessibility service component (implemented in Service).
+ *
+ * @hide
+ */
+ oneway interface IEventListener {
+
+    void setConnection(in IAccessibilityServiceConnection connection);
+
+    void onAccessibilityEvent(in AccessibilityEvent event);
+
+    void onInterrupt();
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9b1f0f9..f9b3d05 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import com.android.internal.policy.PolicyManager;
+
 import android.content.ComponentCallbacks;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -32,11 +34,12 @@
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
 import android.text.method.TextKeyListener;
 import android.util.AttributeSet;
 import android.util.Config;
@@ -58,10 +61,10 @@
 import android.view.WindowManager;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.View.OnCreateContextMenuListener;
+import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
 
-import com.android.internal.policy.PolicyManager;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -2013,7 +2016,24 @@
         }
         return onTrackballEvent(ev);
     }
-    
+
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        event.setClassName(getClass().getName());
+        event.setPackageName(getPackageName());
+
+        LayoutParams params = getWindow().getAttributes();
+        boolean isFullScreen = (params.width == LayoutParams.FILL_PARENT) &&
+            (params.height == LayoutParams.FILL_PARENT);
+        event.setFullScreen(isFullScreen);
+
+        CharSequence title = getTitle();
+        if (!TextUtils.isEmpty(title)) {
+           event.getText().add(title);
+        }
+
+        return true;
+    }
+
     /**
      * Default implementation of
      * {@link android.view.Window.Callback#onCreatePanelView}
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index bb17dc3..81e894f 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -16,8 +16,11 @@
 
 package android.app;
 
-import com.google.android.collect.Maps;
+import com.android.internal.policy.PolicyManager;
 import com.android.internal.util.XmlUtils;
+import com.google.android.collect.Maps;
+
+import org.xmlpull.v1.XmlPullParserException;
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.IBluetoothDevice;
@@ -37,9 +40,9 @@
 import android.content.pm.ComponentInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageStatsObserver;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageManager;
+import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -68,15 +71,15 @@
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.Looper;
-import android.os.RemoteException;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Vibrator;
 import android.os.FileUtils.FileStatus;
@@ -87,10 +90,9 @@
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.WindowManagerImpl;
+import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
 
-import com.android.internal.policy.PolicyManager;
-
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -100,16 +102,14 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.WeakHashMap;
 import java.util.Set;
-import java.util.HashSet;
+import java.util.WeakHashMap;
 import java.util.Map.Entry;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 class ReceiverRestrictedContext extends ContextWrapper {
     ReceiverRestrictedContext(Context base) {
         super(base);
@@ -172,6 +172,7 @@
     private Resources.Theme mTheme = null;
     private PackageManager mPackageManager;
     private NotificationManager mNotificationManager = null;
+    private AccessibilityManager mAccessibilityManager = null;
     private ActivityManager mActivityManager = null;
     private Context mReceiverRestrictedContext = null;
     private SearchManager mSearchManager = null;
@@ -904,6 +905,8 @@
             return getNotificationManager();
         } else if (KEYGUARD_SERVICE.equals(name)) {
             return new KeyguardManager();
+        } else if (ACCESSIBILITY_SERVICE.equals(name)) {
+            return AccessibilityManager.getInstance(this);
         } else if (LOCATION_SERVICE.equals(name)) {
             return getLocationManager();
         } else if (SEARCH_SERVICE.equals(name)) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index b09a57f..222fe75 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,32 +16,34 @@
 
 package android.app;
 
+import com.android.internal.policy.PolicyManager;
+
 import android.content.Context;
 import android.content.DialogInterface;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Bundle;
 import android.util.Config;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.View.OnCreateContextMenuListener;
-
-import com.android.internal.policy.PolicyManager;
+import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
 
 import java.lang.ref.WeakReference;
 
@@ -81,6 +83,7 @@
      * {@hide}
      */
     protected boolean mCancelable = true;
+
     private Message mCancelMessage;
     private Message mDismissMessage;
 
@@ -209,7 +212,9 @@
         if (mShowing) {
             if (Config.LOGV) Log.v(LOG_TAG,
                     "[Dialog] start: already showing, ignore");
-            if (mDecor != null) mDecor.setVisibility(View.VISIBLE);
+            if (mDecor != null) {
+                mDecor.setVisibility(View.VISIBLE);
+            }
             return;
         }
 
@@ -236,7 +241,9 @@
      * Hide the dialog, but do not dismiss it.
      */
     public void hide() {
-        if (mDecor != null) mDecor.setVisibility(View.GONE);
+        if (mDecor != null) {
+            mDecor.setVisibility(View.GONE);
+        }
     }
 
     /**
@@ -266,6 +273,7 @@
         }
 
         mWindowManager.removeView(mDecor);
+
         mDecor = null;
         mWindow.closeAllPanels();
         onStop();
@@ -280,7 +288,7 @@
             Message.obtain(mDismissMessage).sendToTarget();
         }
     }
-    
+
     // internal method to make sure mcreated is set properly without requiring
     // users to call through to super in onCreate
     void dispatchOnCreate(Bundle savedInstanceState) {
@@ -608,6 +616,18 @@
         return onTrackballEvent(ev);
     }
 
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        event.setClassName(getClass().getName());
+        event.setPackageName(mContext.getPackageName());
+
+        LayoutParams params = getWindow().getAttributes();
+        boolean isFullScreen = (params.width == LayoutParams.FILL_PARENT) &&
+            (params.height == LayoutParams.FILL_PARENT);
+        event.setFullScreen(isFullScreen);
+
+        return false;
+    }
+
     /**
      * @see Activity#onCreatePanelView(int)
      */
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f2ad248..c328d1614 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1135,6 +1135,15 @@
     public static final String NOTIFICATION_SERVICE = "notification";
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.view.accessibility.AccessibilityManager} for giving the user
+     * feedback for UI events through the registered event listeners.
+     *
+     * @see #getSystemService
+     * @see android.view.accessibility.AccessibilityManager
+     */
+    public static final String ACCESSIBILITY_SERVICE = "accessibility";
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.app.NotificationManager} for controlling keyguard.
      *
      * @see #getSystemService
diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java
index 1e9b7ae..cf5664c 100644
--- a/core/java/android/preference/CheckBoxPreference.java
+++ b/core/java/android/preference/CheckBoxPreference.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.app.Service;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.TypedArray;
@@ -23,6 +24,8 @@
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Checkable;
 import android.widget.TextView;
 
@@ -42,6 +45,9 @@
     private CharSequence mSummaryOff;
     
     private boolean mChecked;
+    private boolean mSendAccessibilityEventViewClickedType;
+
+    private AccessibilityManager mAccessibilityManager;
     
     private boolean mDisableDependentsState;
     
@@ -55,6 +61,9 @@
         mDisableDependentsState = a.getBoolean(
                 com.android.internal.R.styleable.CheckBoxPreference_disableDependentsState, false);
         a.recycle();
+
+        mAccessibilityManager =
+            (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
     }
 
     public CheckBoxPreference(Context context, AttributeSet attrs) {
@@ -64,14 +73,26 @@
     public CheckBoxPreference(Context context) {
         this(context, null);
     }
-    
+
     @Override
     protected void onBindView(View view) {
         super.onBindView(view);
-        
+
         View checkboxView = view.findViewById(com.android.internal.R.id.checkbox);
         if (checkboxView != null && checkboxView instanceof Checkable) {
             ((Checkable) checkboxView).setChecked(mChecked);
+
+            // send an event to announce the value change of the CheckBox and is done here
+            // because clicking a preference does not immediately change the checked state
+            // for example when enabling the WiFi
+            if (mSendAccessibilityEventViewClickedType &&
+                    mAccessibilityManager.isEnabled() &&
+                    checkboxView.isEnabled()) {
+                mSendAccessibilityEventViewClickedType = false;
+
+                int eventType = AccessibilityEvent.TYPE_VIEW_CLICKED;
+                checkboxView.sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
+            }
         }
 
         // Sync the summary view
@@ -85,7 +106,7 @@
                 summaryView.setText(mSummaryOff);
                 useDefaultSummary = false;
             }
-            
+
             if (useDefaultSummary) {
                 final CharSequence summary = getSummary();
                 if (summary != null) {
@@ -111,6 +132,10 @@
         
         boolean newValue = !isChecked();
         
+        // in onBindView() an AccessibilityEventViewClickedType is sent to announce the change
+        // not sending
+        mSendAccessibilityEventViewClickedType = true;
+
         if (!callChangeListener(newValue)) {
             return;
         }
@@ -124,10 +149,11 @@
      * @param checked The checked state.
      */
     public void setChecked(boolean checked) {
+
         mChecked = checked;
 
         persistBoolean(checked);
-     
+
         notifyDependencyChange(shouldDisableDependents());
         
         notifyChanged();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4dd6524..14ef810 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1905,6 +1905,17 @@
         public static final String USE_GOOGLE_MAIL = "use_google_mail";
     
         /**
+         * If accessibility is enabled.
+         */
+        public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
+
+        /**
+         * List of the enabled accessibility providers.
+         */
+        public static final String ENABLED_ACCESSIBILITY_SERVICES =
+            "enabled_accessibility_services";
+
+        /**
          * Whether to notify the user of open networks.
          * <p>
          * If not connected and the scan results have an open network, we will
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 16b70ed..1564fd0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,9 @@
 
 package android.view;
 
+import com.android.internal.R;
+import com.android.internal.view.menu.MenuBuilder;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -25,12 +28,12 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Shader;
-import android.graphics.Point;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
@@ -42,30 +45,30 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
+import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
-import android.util.SparseArray;
-import android.util.Poolable;
 import android.util.Pool;
-import android.util.Pools;
+import android.util.Poolable;
 import android.util.PoolableManager;
-import android.util.Config;
+import android.util.Pools;
+import android.util.SparseArray;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityEventSource;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Animation;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
 import android.widget.ScrollBarDrawable;
 
-import com.android.internal.R;
-import com.android.internal.view.menu.MenuBuilder;
-
+import java.lang.ref.SoftReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.WeakHashMap;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
 
 /**
  * <p>
@@ -553,7 +556,7 @@
  *
  * @see android.view.ViewGroup
  */
-public class View implements Drawable.Callback, KeyEvent.Callback {
+public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
     private static final boolean DBG = false;
 
     /**
@@ -851,6 +854,18 @@
     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
 
     /**
+     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
+     * should add all focusable Views regardless if they are focusable in touch mode.
+     */
+    public static final int FOCUSABLES_ALL = 0x00000000;
+
+    /**
+     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
+     * should add only Views focusable in touch mode.
+     */
+    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
+
+    /**
      * Use with {@link #focusSearch}. Move focus to the previous selectable
      * item.
      */
@@ -1551,6 +1566,11 @@
     protected int mPaddingBottom;
 
     /**
+     * Briefly describes the view and is primarily used for accessibility support.
+     */
+    private CharSequence mContentDescription;
+
+    /**
      * Cache the paddingRight set by the user to append to the scrollbar's size.
      */
     @ViewDebug.ExportedProperty
@@ -1858,6 +1878,9 @@
                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
                     }
                     break;
+                case com.android.internal.R.styleable.View_contentDescription:
+                    mContentDescription = a.getString(attr);
+                    break;
                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
                     if (!a.getBoolean(attr, true)) {
                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
@@ -2255,6 +2278,8 @@
      *         otherwise is returned.
      */
     public boolean performClick() {
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+
         if (mOnClickListener != null) {
             playSoundEffect(SoundEffectConstants.CLICK);
             mOnClickListener.onClick(this);
@@ -2272,6 +2297,8 @@
      *         otherwise is returned.
      */
     public boolean performLongClick() {
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+
         boolean handled = false;
         if (mOnLongClickListener != null) {
             handled = mOnLongClickListener.onLongClick(View.this);
@@ -2492,6 +2519,10 @@
      *        from (in addition to direction).  Will be <code>null</code> otherwise.
      */
     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+        if (gainFocus) {
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        }
+
         InputMethodManager imm = InputMethodManager.peekInstance();
         if (!gainFocus) {
             if (isPressed()) {
@@ -2514,6 +2545,79 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    public void sendAccessibilityEvent(int eventType) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
+        event.setClassName(getClass().getName());
+        event.setPackageName(getContext().getPackageName());
+        event.setEnabled(isEnabled());
+        event.setContentDescription(mContentDescription);
+
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
+            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
+            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
+            event.setItemCount(focusablesTempList.size());
+            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
+            focusablesTempList.clear();
+        }
+
+        dispatchPopulateAccessibilityEvent(event);
+
+        AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event);
+    }
+
+    /**
+     * Dispatches an {@link AccessibilityEvent} to the {@link View} children
+     * to be populated.
+     *
+     * @param event The event.
+     *
+     * @return True if the event population was completed.
+     */
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        return false;
+    }
+
+    /**
+     * Gets the {@link View} description. It briefly describes the view and is
+     * primarily used for accessibility support. Set this property to enable
+     * better accessibility support for your application. This is especially
+     * true for views that do not have textual representation (For example,
+     * ImageButton).
+     *
+     * @return The content descriptiopn.
+     *
+     * @attr ref android.R.styleable#View_contentDescription
+     */
+    public CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
+    /**
+     * Sets the {@link View} description. It briefly describes the view and is
+     * primarily used for accessibility support. Set this property to enable
+     * better accessibility support for your application. This is especially
+     * true for views that do not have textual representation (For example,
+     * ImageButton).
+     *
+     * @param contentDescription The content description.
+     *
+     * @attr ref android.R.styleable#View_contentDescription
+     */
+    public void setContentDescription(CharSequence contentDescription) {
+        mContentDescription = contentDescription;
+    }
+
+    /**
      * Invoked whenever this view loses focus, either by losing window focus or by losing
      * focus within its window. This method can be used to clear any state tied to the
      * focus. For instance, if a button is held pressed with the trackball and the window
@@ -3222,11 +3326,37 @@
      * @param direction The direction of the focus
      */
     public void addFocusables(ArrayList<View> views, int direction) {
-        if (!isFocusable()) return;
+        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
+    }
 
-        if (isInTouchMode() && !isFocusableInTouchMode()) return;
+    /**
+     * Adds any focusable views that are descendants of this view (possibly
+     * including this view if it is focusable itself) to views. This method
+     * adds all focusable views regardless if we are in touch mode or
+     * only views focusable in touch mode if we are in touch mode depending on
+     * the focusable mode paramater.
+     *
+     * @param views Focusable views found so far or null if all we are interested is
+     *        the number of focusables.
+     * @param direction The direction of the focus.
+     * @param focusableMode The type of focusables to be added.
+     *
+     * @see #FOCUSABLES_ALL
+     * @see #FOCUSABLES_TOUCH_MODE
+     */
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        if (!isFocusable()) {
+            return;
+        }
 
-        views.add(this);
+        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
+                isInTouchMode() && !isFocusableInTouchMode()) {
+            return;
+        }
+
+        if (views != null) {
+            views.add(this);
+        }
     }
 
     /**
@@ -8378,7 +8508,12 @@
          * calling up the hierarchy.
          */
         final Rect mTmpInvalRect = new Rect();
-        
+
+        /**
+         * Temporary list for use in collecting focusable descendents of a view.
+         */
+        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
+
         /**
          * Creates a new set of attachment information with the specified
          * events handler and thread.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index db5177f..bf04dcd 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -24,15 +24,16 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.Region;
 import android.graphics.RectF;
+import android.graphics.Region;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseArray;
-import android.util.Config;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.LayoutAnimationController;
@@ -601,6 +602,14 @@
      */
     @Override
     public void addFocusables(ArrayList<View> views, int direction) {
+        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
         final int focusableCount = views.size();
 
         final int descendantFocusability = getDescendantFocusability();
@@ -612,7 +621,7 @@
             for (int i = 0; i < count; i++) {
                 final View child = children[i];
                 if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
-                    child.addFocusables(views, direction);
+                    child.addFocusables(views, direction, focusableMode);
                 }
             }
         }
@@ -625,7 +634,7 @@
             descendantFocusability != FOCUS_AFTER_DESCENDANTS ||
                 // No focusable descendants
                 (focusableCount == views.size())) {
-            super.addFocusables(views, direction);
+            super.addFocusables(views, direction, focusableMode);
         }
     }
 
@@ -1020,6 +1029,15 @@
         }
     }
 
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean populated = false;
+        for (int i = 0, count = getChildCount(); i < count; i++) {
+            populated |= getChildAt(i).dispatchPopulateAccessibilityEvent(event);
+        }
+        return populated;
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index dbfb194..7cd65e2 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -34,6 +34,8 @@
 import android.util.EventLog;
 import android.util.SparseArray;
 import android.view.View.MeasureSpec;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Scroller;
@@ -640,6 +642,7 @@
             host.dispatchAttachedToWindow(attachInfo, 0);
             getRunQueue().executeActions(attachInfo.mHandler);
             //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
+
         } else {
             desiredWindowWidth = mWinFrame.width();
             desiredWindowHeight = mWinFrame.height();
@@ -1723,7 +1726,7 @@
                     }
                     mView.dispatchWindowFocusChanged(hasWindowFocus);
                 }
-                
+
                 // Note: must be done after the focus change callbacks,
                 // so all of the view state is set up correctly.
                 if (hasWindowFocus) {
@@ -1741,6 +1744,10 @@
                                 ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
                     mHasHadWindowFocus = true;
                 }
+
+                if (hasWindowFocus && mView != null) {
+                    sendAccessibilityEvents();
+                }
             }
         } break;
         case DIE:
@@ -2526,6 +2533,21 @@
         sendMessage(msg);
     }
 
+    /**
+     * The window is getting focus so if there is anything focused/selected
+     * send an {@link AccessibilityEvent} to announce that.
+     */
+    private void sendAccessibilityEvents() {
+        if (!AccessibilityManager.getInstance(mView.getContext()).isEnabled()) {
+            return;
+        }
+        mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        View focusedView = mView.findFocus();
+        if (focusedView != null && focusedView != mView) {
+            focusedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        }
+    }
+
     public boolean showContextMenuForChild(View originalView) {
         return false;
     }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 428de67..b0e738c 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -24,7 +24,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
 
 /**
  * Abstract base class for a top-level window look and behavior policy.  An
@@ -153,7 +153,16 @@
          * @return boolean Return true if this event was consumed.
          */
         public boolean dispatchTrackballEvent(MotionEvent event);
-        
+
+        /**
+         * Called to process population of {@link AccessibilityEvent}s.
+         *
+         * @param event The event.
+         *
+         * @return boolean Return true if event population was completed.
+         */
+        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
+
         /**
          * Instantiate the view to display in the panel for 'featureId'.
          * You can return null, in which case the default content (typically
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 755d7b8..0973599 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -173,7 +173,6 @@
             mRoots[index] = root;
             mParams[index] = wparams;
         }
-
         // do this last because it fires off messages to start doing things
         root.setView(view, wparams, panelParentView);
     }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.aidl b/core/java/android/view/accessibility/AccessibilityEvent.aidl
new file mode 100644
index 0000000..cee3604
--- /dev/null
+++ b/core/java/android/view/accessibility/AccessibilityEvent.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2009, 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.view.accessibility;
+
+parcelable AccessibilityEvent;
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
new file mode 100644
index 0000000..c22f991
--- /dev/null
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2009 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.view.accessibility;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents accessibility events that are sent by the system when
+ * something notable happens in the user interface. For example, when a
+ * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
+ * <p>
+ * This class represents various semantically different accessibility event
+ * types. Each event type has associated a set of related properties. In other
+ * words, each event type is characterized via a subset of the properties exposed
+ * by this class. For each event type there is a corresponding constant defined
+ * in this class. Since some event types are semantically close there are mask
+ * constants that group them together. Follows a specification of the event
+ * types and their associated properties:
+ * <p>
+ * <b>VIEW TYPES</b> <br>
+ * <p>
+ * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
+ * Type:{@link #TYPE_VIEW_CLICKED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()},
+ * {@link #isChecked()},
+ * {@link #isEnabled()},
+ * {@link #isPassword()},
+ * {@link #getItemCount()},
+ * {@link #getCurrentItemIndex()}
+ * <p>
+ * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
+ * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()},
+ * {@link #isChecked()},
+ * {@link #isEnabled()},
+ * {@link #isPassword()},
+ * {@link #getItemCount()},
+ * {@link #getCurrentItemIndex()}
+ * <p>
+ * <b>View selected</b> - represents the event of selecting an item usually in
+ * the context of an {@link android.widget.AdapterView}. <br>
+ * Type: {@link #TYPE_VIEW_SELECTED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()},
+ * {@link #isChecked()},
+ * {@link #isEnabled()},
+ * {@link #isPassword()},
+ * {@link #getItemCount()},
+ * {@link #getCurrentItemIndex()}
+ * <p>
+ * <b>View focused</b> - represents the event of focusing a
+ * {@link android.view.View}. <br>
+ * Type: {@link #TYPE_VIEW_FOCUSED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()},
+ * {@link #isChecked()},
+ * {@link #isEnabled()},
+ * {@link #isPassword()},
+ * {@link #getItemCount()},
+ * {@link #getCurrentItemIndex()}
+ * <p>
+ * <b>View text changed</b> - represents the event of changing the text of an
+ * {@link android.widget.EditText}. <br>
+ * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()},
+ * {@link #isChecked()},
+ * {@link #isEnabled()},
+ * {@link #isPassword()},
+ * {@link #getItemCount()},
+ * {@link #getCurrentItemIndex()},
+ * {@link #getFromIndex()},
+ * {@link #getAddedCount()},
+ * {@link #getRemovedCount()},
+ * {@link #getBeforeText()}
+ * <p>
+ * <b>TRANSITION TYPES</b> <br>
+ * <p>
+ * <b>Window state changed</b> - represents the event of opening/closing a
+ * {@link android.widget.PopupWindow}, {@link android.view.Menu},
+ * {@link android.app.Dialog}, etc. <br>
+ * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()}
+ * <p>
+ * <b>NOTIFICATION TYPES</b> <br>
+ * <p>
+ * <b>Notification state changed</b> - represents the event showing/hiding
+ * {@link android.app.Notification}.
+ * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()}
+ * {@link #getParcelableData()}
+ * <p>
+ * <b>Security note</b>
+ * <p>
+ * Since an event contains the text of its source privacy can be compromised by leaking of
+ * sensitive information such as passwords. To address this issue any event fired in response
+ * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password.
+ *
+ * @see android.view.accessibility.AccessibilityManager
+ * @see android.accessibilityservice.AccessibilityService
+ */
+public final class AccessibilityEvent implements Parcelable {
+
+    /**
+     * Invalid selection/focus position.
+     *
+     * @see #getCurrentItemIndex()
+     */
+    public static final int INVALID_POSITION = -1;
+
+    /**
+     * Maximum length of the text fields.
+     *
+     * @see #getBeforeText()
+     * @see #getText()
+     */
+    public static final int MAX_TEXT_LENGTH = 500;
+
+    /**
+     * Represents the event of clicking on a {@link android.view.View} like
+     * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
+     */
+    public static final int TYPE_VIEW_CLICKED = 0x00000001;
+
+    /**
+     * Represents the event of long clicking on a {@link android.view.View} like
+     * {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
+     */
+    public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
+
+    /**
+     * Represents the event of selecting an item usually in the context of an
+     * {@link android.widget.AdapterView}.
+     */
+    public static final int TYPE_VIEW_SELECTED = 0x00000004;
+
+    /**
+     * Represents the event of focusing a {@link android.view.View}.
+     */
+    public static final int TYPE_VIEW_FOCUSED = 0x00000008;
+
+    /**
+     * Represents the event of changing the text of an {@link android.widget.EditText}.
+     */
+    public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
+
+    /**
+     * Represents the event of opening/closing a {@link android.widget.PopupWindow},
+     * {@link android.view.Menu}, {@link android.app.Dialog}, etc.
+     */
+    public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
+
+    /**
+     * Represents the event showing/hiding a {@link android.app.Notification}.
+     */
+    public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
+
+    /**
+     * Mask for {@link AccessibilityEvent} all types.
+     *
+     * @see #TYPE_VIEW_CLICKED
+     * @see #TYPE_VIEW_LONG_CLICKED
+     * @see #TYPE_VIEW_SELECTED
+     * @see #TYPE_VIEW_FOCUSED
+     * @see #TYPE_VIEW_TEXT_CHANGED
+     * @see #TYPE_WINDOW_STATE_CHANGED
+     * @see #TYPE_NOTIFICATION_STATE_CHANGED
+     */
+    public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
+
+    private static final int MAX_POOL_SIZE = 2;
+    private static final Object mPoolLock = new Object();
+    private static AccessibilityEvent sPool;
+    private static int sPoolSize;
+
+    private static final int CHECKED = 0x00000001;
+    private static final int ENABLED = 0x00000002;
+    private static final int PASSWORD = 0x00000004;
+    private static final int FULL_SCREEN = 0x00000080;
+
+    private AccessibilityEvent mNext;
+
+    private int mEventType;
+    private int mBooleanProperties;
+    private int mCurrentItemIndex;
+    private int mItemCount;
+    private int mFromIndex;
+    private int mAddedCount;
+    private int mRemovedCount;
+
+    private long mEventTime;
+
+    private CharSequence mClassName;
+    private CharSequence mPackageName;
+    private CharSequence mContentDescription;
+    private CharSequence mBeforeText;
+
+    private Parcelable mParcelableData;
+
+    private final List<CharSequence> mText = new ArrayList<CharSequence>();
+
+    private boolean mIsInPool;
+
+    /*
+     * Hide constructor from clients.
+     */
+    private AccessibilityEvent() {
+        mCurrentItemIndex = INVALID_POSITION;
+    }
+
+    /**
+     * Gets if the source is checked.
+     *
+     * @return True if the view is checked, false otherwise.
+     */
+    public boolean isChecked() {
+        return getBooleanProperty(CHECKED);
+    }
+
+    /**
+     * Sets if the source is checked.
+     *
+     * @param isChecked True if the view is checked, false otherwise.
+     */
+    public void setChecked(boolean isChecked) {
+        setBooleanProperty(CHECKED, isChecked);
+    }
+
+    /**
+     * Gets if the source is enabled.
+     *
+     * @return True if the view is enabled, false otherwise.
+     */
+    public boolean isEnabled() {
+        return getBooleanProperty(ENABLED);
+    }
+
+    /**
+     * Sets if the source is enabled.
+     *
+     * @param isEnabled True if the view is enabled, false otherwise.
+     */
+    public void setEnabled(boolean isEnabled) {
+        setBooleanProperty(ENABLED, isEnabled);
+    }
+
+    /**
+     * Gets if the source is a password field.
+     *
+     * @return True if the view is a password field, false otherwise.
+     */
+    public boolean isPassword() {
+        return getBooleanProperty(PASSWORD);
+    }
+
+    /**
+     * Sets if the source is a password field.
+     *
+     * @param isPassword True if the view is a password field, false otherwise.
+     */
+    public void setPassword(boolean isPassword) {
+        setBooleanProperty(PASSWORD, isPassword);
+    }
+
+    /**
+     * Sets if the source is taking the entire screen.
+     *
+     * @param isFullScreen True if the source is full screen, false otherwise.
+     */
+    public void setFullScreen(boolean isFullScreen) {
+        setBooleanProperty(FULL_SCREEN, isFullScreen);
+    }
+
+    /**
+     * Gets if the source is taking the entire screen.
+     *
+     * @return True if the source is full screen, false otherwise.
+     */
+    public boolean isFullScreen() {
+        return getBooleanProperty(FULL_SCREEN);
+    }
+
+    /**
+     * Gets the event type.
+     *
+     * @return The event type.
+     */
+    public int getEventType() {
+        return mEventType;
+    }
+
+    /**
+     * Sets the event type.
+     *
+     * @param eventType The event type.
+     */
+    public void setEventType(int eventType) {
+        mEventType = eventType;
+    }
+
+    /**
+     * Gets the number of items that can be visited.
+     *
+     * @return The number of items.
+     */
+    public int getItemCount() {
+        return mItemCount;
+    }
+
+    /**
+     * Sets the number of items that can be visited.
+     *
+     * @param itemCount The number of items.
+     */
+    public void setItemCount(int itemCount) {
+        mItemCount = itemCount;
+    }
+
+    /**
+     * Gets the index of the source in the list of items the can be visited.
+     *
+     * @return The current item index.
+     */
+    public int getCurrentItemIndex() {
+        return mCurrentItemIndex;
+    }
+
+    /**
+     * Sets the index of the source in the list of items that can be visited.
+     *
+     * @param currentItemIndex The current item index.
+     */
+    public void setCurrentItemIndex(int currentItemIndex) {
+        mCurrentItemIndex = currentItemIndex;
+    }
+
+    /**
+     * Gets the index of the first character of the changed sequence.
+     *
+     * @return The index of the first character.
+     */
+    public int getFromIndex() {
+        return mFromIndex;
+    }
+
+    /**
+     * Sets the index of the first character of the changed sequence.
+     *
+     * @param fromIndex The index of the first character.
+     */
+    public void setFromIndex(int fromIndex) {
+        mFromIndex = fromIndex;
+    }
+
+    /**
+     * Gets the number of added characters.
+     *
+     * @return The number of added characters.
+     */
+    public int getAddedCount() {
+        return mAddedCount;
+    }
+
+    /**
+     * Sets the number of added characters.
+     *
+     * @param addedCount The number of added characters.
+     */
+    public void setAddedCount(int addedCount) {
+        mAddedCount = addedCount;
+    }
+
+    /**
+     * Gets the number of removed characters.
+     *
+     * @return The number of removed characters.
+     */
+    public int getRemovedCount() {
+        return mRemovedCount;
+    }
+
+    /**
+     * Sets the number of removed characters.
+     *
+     * @param removedCount The number of removed characters.
+     */
+    public void setRemovedCount(int removedCount) {
+        mRemovedCount = removedCount;
+    }
+
+    /**
+     * Gets the time in which this event was sent.
+     *
+     * @return The event time.
+     */
+    public long getEventTime() {
+        return mEventTime;
+    }
+
+    /**
+     * Sets the time in which this event was sent.
+     *
+     * @param eventTime The event time.
+     */
+    public void setEventTime(long eventTime) {
+        mEventTime = eventTime;
+    }
+
+    /**
+     * Gets the class name of the source.
+     *
+     * @return The class name.
+     */
+    public CharSequence getClassName() {
+        return mClassName;
+    }
+
+    /**
+     * Sets the class name of the source.
+     *
+     * @param className The lass name.
+     */
+    public void setClassName(CharSequence className) {
+        mClassName = className;
+    }
+
+    /**
+     * Gets the package name of the source.
+     *
+     * @return The package name.
+     */
+    public CharSequence getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Sets the package name of the source.
+     *
+     * @param packageName The package name.
+     */
+    public void setPackageName(CharSequence packageName) {
+        mPackageName = packageName;
+    }
+
+    /**
+     * Gets the text of the event. The index in the list represents the priority
+     * of the text. Specifically, the lower the index the higher the priority.
+     *
+     * @return The text.
+     */
+    public List<CharSequence> getText() {
+        return mText;
+    }
+
+    /**
+     * Sets the text before a change.
+     *
+     * @return The text before the change.
+     */
+    public CharSequence getBeforeText() {
+        return mBeforeText;
+    }
+
+    /**
+     * Sets the text before a change.
+     *
+     * @param beforeText The text before the change.
+     */
+    public void setBeforeText(CharSequence beforeText) {
+        mBeforeText = beforeText;
+    }
+
+    /**
+     * Gets the description of the source.
+     *
+     * @return The description.
+     */
+    public CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
+    /**
+     * Sets the description of the source.
+     *
+     * @param contentDescription The description.
+     */
+    public void setContentDescription(CharSequence contentDescription) {
+        mContentDescription = contentDescription;
+    }
+
+    /**
+     * Gets the {@link Parcelable} data.
+     *
+     * @return The parcelable data.
+     */
+    public Parcelable getParcelableData() {
+        return mParcelableData;
+    }
+
+    /**
+     * Sets the {@link Parcelable} data of the event.
+     *
+     * @param parcelableData The parcelable data.
+     */
+    public void setParcelableData(Parcelable parcelableData) {
+        mParcelableData = parcelableData;
+    }
+
+    /**
+     * Returns a cached instance if such is available or a new one is
+     * instantiated with type property set.
+     *
+     * @param eventType The event type.
+     * @return An instance.
+     */
+    public static AccessibilityEvent obtain(int eventType) {
+        AccessibilityEvent event = AccessibilityEvent.obtain();
+        event.setEventType(eventType);
+        return event;
+    }
+
+    /**
+     * Returns a cached instance if such is available or a new one is
+     * instantiated.
+     *
+     * @return An instance.
+     */
+    public static AccessibilityEvent obtain() {
+        synchronized (mPoolLock) {
+            if (sPool != null) {
+                AccessibilityEvent event = sPool;
+                sPool = sPool.mNext;
+                sPoolSize--;
+                event.mNext = null;
+                event.mIsInPool = false;
+                return event;
+            }
+            return new AccessibilityEvent();
+        }
+    }
+
+    /**
+     * Return an instance back to be reused.
+     * <p>
+     * <b>Note: You must not touch the object after calling this function.</b>
+     */
+    public void recycle() {
+        if (mIsInPool) {
+            return;
+        }
+
+        clear();
+        synchronized (mPoolLock) {
+            if (sPoolSize <= MAX_POOL_SIZE) {
+                mNext = sPool;
+                sPool = this;
+                mIsInPool = true;
+                sPoolSize++;
+            }
+        }
+    }
+
+    /**
+     * Clears the state of this instance.
+     */
+    private void clear() {
+        mEventType = 0;
+        mBooleanProperties = 0;
+        mCurrentItemIndex = INVALID_POSITION;
+        mItemCount = 0;
+        mFromIndex = 0;
+        mAddedCount = 0;
+        mRemovedCount = 0;
+        mEventTime = 0;
+        mClassName = null;
+        mPackageName = null;
+        mContentDescription = null;
+        mBeforeText = null;
+        mText.clear();
+    }
+
+    /**
+     * Gets the value of a boolean property.
+     *
+     * @param property The property.
+     * @return The value.
+     */
+    private boolean getBooleanProperty(int property) {
+        return (mBooleanProperties & property) == property;
+    }
+
+    /**
+     * Sets a boolean property.
+     *
+     * @param property The property.
+     * @param value The value.
+     */
+    private void setBooleanProperty(int property, boolean value) {
+        if (value) {
+            mBooleanProperties |= property;
+        } else {
+            mBooleanProperties &= ~property;
+        }
+    }
+
+    /**
+     * Creates a new instance from a {@link Parcel}.
+     *
+     * @param parcel A parcel containing the state of a {@link AccessibilityEvent}.
+     */
+    public void initFromParcel(Parcel parcel) {
+        mEventType = parcel.readInt();
+        mBooleanProperties = parcel.readInt();
+        mCurrentItemIndex = parcel.readInt();
+        mItemCount = parcel.readInt();
+        mFromIndex = parcel.readInt();
+        mAddedCount = parcel.readInt();
+        mRemovedCount = parcel.readInt();
+        mEventTime = parcel.readLong();
+        mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+        mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+        mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+        mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+        mParcelableData = parcel.readParcelable(null);
+        parcel.readList(mText, null);
+    }
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mEventType);
+        parcel.writeInt(mBooleanProperties);
+        parcel.writeInt(mCurrentItemIndex);
+        parcel.writeInt(mItemCount);
+        parcel.writeInt(mFromIndex);
+        parcel.writeInt(mAddedCount);
+        parcel.writeInt(mRemovedCount);
+        parcel.writeLong(mEventTime);
+        TextUtils.writeToParcel(mClassName, parcel, 0);
+        TextUtils.writeToParcel(mPackageName, parcel, 0);
+        TextUtils.writeToParcel(mContentDescription, parcel, 0);
+        TextUtils.writeToParcel(mBeforeText, parcel, 0);
+        parcel.writeParcelable(mParcelableData, flags);
+        parcel.writeList(mText);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(super.toString());
+        builder.append("; EventType: " + mEventType);
+        builder.append("; EventTime: " + mEventTime);
+        builder.append("; ClassName: " + mClassName);
+        builder.append("; PackageName: " + mPackageName);
+        builder.append("; Text: " + mText);
+        builder.append("; ContentDescription: " + mContentDescription);
+        builder.append("; ItemCount: " + mItemCount);
+        builder.append("; CurrentItemIndex: " + mCurrentItemIndex);
+        builder.append("; IsEnabled: " + isEnabled());
+        builder.append("; IsPassword: " + isPassword());
+        builder.append("; IsChecked: " + isChecked());
+        builder.append("; IsFullScreen: " + isFullScreen());
+        builder.append("; BeforeText: " + mBeforeText);
+        builder.append("; FromIndex: " + mFromIndex);
+        builder.append("; AddedCount: " + mAddedCount);
+        builder.append("; RemovedCount: " + mRemovedCount);
+        builder.append("; ParcelableData: " + mParcelableData);
+        return builder.toString();
+    }
+
+    /**
+     * @see Parcelable.Creator
+     */
+    public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
+            new Parcelable.Creator<AccessibilityEvent>() {
+        public AccessibilityEvent createFromParcel(Parcel parcel) {
+            AccessibilityEvent event = AccessibilityEvent.obtain();
+            event.initFromParcel(parcel);
+            return event;
+        }
+
+        public AccessibilityEvent[] newArray(int size) {
+            return new AccessibilityEvent[size];
+        }
+    };
+}
diff --git a/core/java/android/view/accessibility/AccessibilityEventSource.java b/core/java/android/view/accessibility/AccessibilityEventSource.java
new file mode 100644
index 0000000..3d70959
--- /dev/null
+++ b/core/java/android/view/accessibility/AccessibilityEventSource.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 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.view.accessibility;
+
+/**
+ * This interface is implemented by classes source of {@link AccessibilityEvent}s.
+ */
+public interface AccessibilityEventSource {
+
+    /**
+     * Handles the request for sending an {@link AccessibilityEvent} given
+     * the event type. The method must first check if accessibility is on
+     * via calling {@link AccessibilityManager#isEnabled()}, obtain
+     * an {@link AccessibilityEvent} from the event pool through calling
+     * {@link AccessibilityEvent#obtain(int)}, populate the event, and
+     * send it for dispatch via calling
+     * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)}.
+     *
+     * @see AccessibilityEvent
+     * @see AccessibilityManager
+     *
+     * @param eventType The event type.
+     */
+    public void sendAccessibilityEvent(int eventType);
+
+    /**
+     * Handles the request for sending an {@link AccessibilityEvent}. The
+     * method does not guarantee to check if accessibility is on before
+     * sending the event for dispatch. It is responsibility of the caller
+     * to do the check via calling {@link AccessibilityManager#isEnabled()}.
+     *
+     * @see AccessibilityEvent
+     * @see AccessibilityManager
+     *
+     * @param event The event.
+     */
+    public void sendAccessibilityEventUnchecked(AccessibilityEvent event);
+}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
new file mode 100644
index 0000000..0186270
--- /dev/null
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009 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.view.accessibility;
+
+import static android.util.Config.LOGV;
+
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * System level service that serves as an event dispatch for {@link AccessibilityEvent}s.
+ * Such events are generated when something notable happens in the user interface,
+ * for example an {@link android.app.Activity} starts, the focus or selection of a
+ * {@link android.view.View} changes etc. Parties interested in handling accessibility
+ * events implement and register an accessibility service which extends
+ * {@link android.accessibilityservice.AccessibilityService}.
+ *
+ * @see AccessibilityEvent
+ * @see android.accessibilityservice.AccessibilityService
+ * @see android.content.Context#getSystemService
+ */
+public final class AccessibilityManager {
+    private static final String LOG_TAG = "AccessibilityManager";
+
+    static final Object sInstanceSync = new Object();
+
+    private static AccessibilityManager sInstance;
+
+    private static final int DO_SET_ENABLED = 10;
+
+    final IAccessibilityManager mService;
+
+    final Handler mHandler;
+
+    boolean mIsEnabled;
+
+    final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
+        public void setEnabled(boolean enabled) {
+            mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget();
+        }
+    };
+
+    class MyHandler extends Handler {
+
+        MyHandler(Looper mainLooper) {
+            super(mainLooper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case DO_SET_ENABLED :
+                    synchronized (mHandler) {
+                        mIsEnabled = (message.arg1 == 1);
+                    }
+                    return;
+                default :
+                    Log.w(LOG_TAG, "Unknown message type: " + message.what);
+            }
+        }
+    }
+
+    /**
+     * Get an AccessibilityManager instance (create one if necessary).
+     *
+     * @hide
+     */
+    public static AccessibilityManager getInstance(Context context) {
+        synchronized (sInstanceSync) {
+            if (sInstance == null) {
+                sInstance = new AccessibilityManager(context);
+            }
+        }
+        return sInstance;
+    }
+
+    /**
+     * Create an instance.
+     *
+     * @param context A {@link Context}.
+     */
+    private AccessibilityManager(Context context) {
+        mHandler = new MyHandler(context.getMainLooper());
+        IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+        mService = IAccessibilityManager.Stub.asInterface(iBinder);
+        try {
+            mService.addClient(mClient);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
+        }
+    }
+
+    /**
+     * Returns if the {@link AccessibilityManager} is enabled.
+     *
+     * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
+     */
+    public boolean isEnabled() {
+        synchronized (mHandler) {
+            return mIsEnabled;
+        }
+    }
+
+    /**
+     * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not
+     * enabled the call is a NOOP.
+     *
+     * @param event The {@link AccessibilityEvent}.
+     *
+     * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent}
+     *         while accessibility is not enabled.
+     */
+    public void sendAccessibilityEvent(AccessibilityEvent event) {
+        if (!mIsEnabled) {
+            throw new IllegalStateException("Accessibility off. Did you forget to check that?");
+        }
+        boolean doRecycle = false;
+        try {
+            event.setEventTime(SystemClock.uptimeMillis());
+            // it is possible that this manager is in the same process as the service but
+            // client using it is called through Binder from another process. Example: MMS
+            // app adds a SMS notification and the NotificationManagerService calls this method
+            long identityToken = Binder.clearCallingIdentity();
+            doRecycle = mService.sendAccessibilityEvent(event);
+            Binder.restoreCallingIdentity(identityToken);
+            if (LOGV) {
+                Log.i(LOG_TAG, event + " sent");
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error during sending " + event + " ", re);
+        } finally {
+            if (doRecycle) {
+                event.recycle();
+            }
+        }
+    }
+
+    /**
+     * Requests interruption of the accessibility feedback from all accessibility services.
+     */
+    public void interrupt() {
+        if (!mIsEnabled) {
+            throw new IllegalStateException("Accessibility off. Did you forget to check that?");
+        }
+        try {
+            mService.interrupt();
+            if (LOGV) {
+                Log.i(LOG_TAG, "Requested interrupt from all services");
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while requesting interrupt from all services. ", re);
+        }
+    }
+
+    /**
+     * Returns the {@link ServiceInfo}s of the installed accessibility services.
+     *
+     * @return An unmodifiable list with {@link ServiceInfo}s.
+     */
+    public List<ServiceInfo> getAccessibilityServiceList() {
+        List<ServiceInfo> services = null;
+        try {
+            services = mService.getAccessibilityServiceList();
+            if (LOGV) {
+                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
+        }
+        return Collections.unmodifiableList(services);
+    }
+}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
new file mode 100644
index 0000000..32788be
--- /dev/null
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -0,0 +1,39 @@
+/* //device/java/android/android/app/INotificationManager.aidl
+**
+** Copyright 2009, 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.view.accessibility;
+
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.IAccessibilityManagerClient;
+import android.content.pm.ServiceInfo;
+
+/**
+ * Interface implemented by the AccessibilityManagerService called by
+ * the AccessibilityMasngers.
+ *
+ * @hide
+ */
+interface IAccessibilityManager {
+
+    void addClient(IAccessibilityManagerClient client);
+
+    boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
+
+    List<ServiceInfo> getAccessibilityServiceList();
+
+    void interrupt();
+}
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
new file mode 100644
index 0000000..1eb60fc
--- /dev/null
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 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.view.accessibility;
+
+/**
+ * Interface a client of the IAccessibilityManager implements to
+ * receive information about changes in the manager state.
+ *
+ * @hide
+ */
+oneway interface IAccessibilityManagerClient {
+
+    void setEnabled(boolean enabled);
+
+}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 173e80f..7d2fcbc 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -24,11 +24,12 @@
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.ContextMenu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewDebug;
 import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
 
 
 /**
@@ -618,7 +619,9 @@
     }
 
     /**
-     * Sets the currently selected item
+     * Sets the currently selected item. To support accessibility subclasses that
+     * override this method must invoke the overriden super method first.
+     *
      * @param position Index (starting at 0) of the data item to be selected.
      */
     public abstract void setSelection(int position);
@@ -844,6 +847,11 @@
                 fireOnSelected();
             }
         }
+
+        // we fire selection events here not in View
+        if (mSelectedPosition != ListView.INVALID_POSITION && isShown() && !isInTouchMode()) {
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+        }
     }
 
     private void fireOnSelected() {
@@ -861,6 +869,35 @@
     }
 
     @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean populated = false;
+        // This is an exceptional case which occurs when a window gets the
+        // focus and sends a focus event via its focused child to announce
+        // current focus/selection. AdapterView fires selection but not focus
+        // events so we change the event type here.
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+            event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
+        }
+
+        // we send selection events only from AdapterView to avoid
+        // generation of such event for each child
+        View selectedView = getSelectedView();
+        if (selectedView != null) {
+            populated = selectedView.dispatchPopulateAccessibilityEvent(event);
+        }
+
+        if (!populated) {
+            if (selectedView != null) {
+                event.setEnabled(selectedView.isEnabled());
+            }
+            event.setItemCount(getCount());
+            event.setCurrentItemIndex(getSelectedItemPosition());
+        }
+
+        return populated;
+    }
+
+    @Override
     protected boolean canAnimate() {
         return super.canAnimate() && mItemCount > 0;
     }
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index abcc715..fd590ed 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -16,14 +16,15 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.Gravity;
-
-import com.android.internal.R;
+import android.view.accessibility.AccessibilityEvent;
 
 
 /**
@@ -194,5 +195,13 @@
             invalidate();
         }
     }
-    
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean populated = super.dispatchPopulateAccessibilityEvent(event);
+        if (!populated) {
+            event.setChecked(mChecked);
+        }
+        return populated;
+    }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index d4482dc..98b0976 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -26,7 +26,7 @@
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.view.Gravity;
-
+import android.view.accessibility.AccessibilityEvent;
 
 /**
  * <p>
@@ -124,6 +124,7 @@
             if (mOnCheckedChangeWidgetListener != null) {
                 mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
             }
+
             mBroadcasting = false;            
         }
     }
@@ -205,6 +206,25 @@
     }
 
     @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean populated = super.dispatchPopulateAccessibilityEvent(event);
+
+        if (!populated) {
+            int resourceId = 0;
+            if (mChecked) {
+                resourceId = R.string.accessibility_compound_button_selected;
+            } else {
+                resourceId = R.string.accessibility_compound_button_unselected;
+            }
+            String state = getResources().getString(resourceId);
+            event.getText().add(state);
+            event.setChecked(mChecked);
+        }
+
+        return populated;
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 480b0b8..2796774 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -32,6 +32,8 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.RemoteViews.RemoteView;
 
 
@@ -848,7 +850,7 @@
     public int getBaseline() {
         return mBaselineAligned ? getMeasuredHeight() : -1;
     }
-    
+
     /**
      * Set a tinting option for the image.
      * 
@@ -878,7 +880,7 @@
             invalidate();
         }
     }
-    
+
     public void setAlpha(int alpha) {
         alpha &= 0xFF;          // keep it legal
         if (mAlpha != alpha) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 5472d68..c21c7fa 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -35,6 +35,7 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.SoundEffectConstants;
+import android.view.accessibility.AccessibilityEvent;
 
 import com.google.android.collect.Lists;
 import com.android.internal.R;
@@ -1845,6 +1846,32 @@
         }
     }
 
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean populated = super.dispatchPopulateAccessibilityEvent(event);
+
+        if (!populated) {
+            int itemCount = 0;
+            int currentItemIndex = getSelectedItemPosition();
+
+            ListAdapter adapter = getAdapter();
+            if (adapter != null) {
+                for (int i = 0, count = adapter.getCount(); i < count; i++) {
+                    if (adapter.isEnabled(i)) {
+                        itemCount++;
+                    } else if (i <= currentItemIndex) {
+                        currentItemIndex--;
+                    }
+                }
+            }
+
+            event.setItemCount(itemCount);
+            event.setCurrentItemIndex(currentItemIndex);
+        }
+
+        return populated;
+    }
+
     /**
      * setSelectionAfterHeaderView set the selection to be the first list item
      * after the header views.
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 78c7bd8..975277b 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -18,6 +18,8 @@
 
 import com.android.internal.R;
 
+import android.content.Context;
+import android.content.res.TypedArray;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -33,8 +35,6 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.os.IBinder;
-import android.content.Context;
-import android.content.res.TypedArray;
 import android.util.AttributeSet;
 
 import java.lang.ref.WeakReference;
@@ -1017,6 +1017,7 @@
             unregisterForScrollChanged();
 
             mWindowManager.removeView(mPopupView);
+
             if (mPopupView != mContentView && mPopupView instanceof ViewGroup) {
                 ((ViewGroup) mPopupView).removeView(mContentView);
             }
@@ -1316,7 +1317,16 @@
                 return super.onTouchEvent(event);
             }
         }
-        
+
+        @Override
+        public void sendAccessibilityEvent(int eventType) {
+            // clinets are interested in the content not the container, make it event source
+            if (mContentView != null) {
+                mContentView.sendAccessibilityEvent(eventType);
+            } else {
+                super.sendAccessibilityEvent(eventType);
+            }
+        }
     }
     
 }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index edbb3db..ef240e0 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -16,17 +16,22 @@
 
 package android.widget;
 
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Gravity;
-import android.view.ViewDebug;
-import android.widget.RemoteViews.RemoteView;
-import android.graphics.Rect;
 import com.android.internal.R;
 
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.RemoteViews.RemoteView;
+
+import java.util.Comparator;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 /**
  * A Layout where the positions of the children can be described in relation to each other or to the
@@ -137,6 +142,8 @@
     private final Rect mSelfBounds = new Rect();
     private int mIgnoreGravity;
 
+    private static SortedSet<View> mTopToBottomLeftToRightSet = null;
+
     public RelativeLayout(Context context) {
         super(context);
     }
@@ -782,6 +789,57 @@
         return new LayoutParams(p);
     }
 
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        if (mTopToBottomLeftToRightSet == null) {
+            mTopToBottomLeftToRightSet = new TreeSet<View>(new TopToBottomLeftToRightComparator());
+        }
+
+        // sort children top-to-bottom and left-to-right
+        for (int i = 0, count = getChildCount(); i < count; i++) {
+            mTopToBottomLeftToRightSet.add(getChildAt(i));
+        }
+
+        for (View view : mTopToBottomLeftToRightSet) {
+            if (view.dispatchPopulateAccessibilityEvent(event)) {
+                mTopToBottomLeftToRightSet.clear();
+                return true;
+            }
+        }
+
+        mTopToBottomLeftToRightSet.clear();
+        return false;
+    }
+
+    /**
+     * Compares two views in left-to-right and top-to-bottom fashion.
+     */
+     private class TopToBottomLeftToRightComparator implements Comparator<View> {
+        public int compare(View first, View second) {
+            // top - bottom
+            int topDifference = first.getTop() - second.getTop();
+            if (topDifference != 0) {
+                return topDifference;
+            }
+            // left - right
+            int leftDifference = first.getLeft() - second.getLeft();
+            if (leftDifference != 0) {
+                return leftDifference;
+            }
+            // break tie by height
+            int heightDiference = first.getHeight() - second.getHeight();
+            if (heightDiference != 0) {
+                return heightDiference;
+            }
+            // break tie by width
+            int widthDiference = first.getWidth() - second.getWidth();
+            if (widthDiference != 0) {
+                return widthDiference;
+            }
+            return 0;
+        }
+    }
+
     /**
      * Per-child layout information associated with RelativeLayout.
      *
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index 92561ed..f706744 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -16,21 +16,22 @@
 
 package android.widget;
 
-import android.view.ViewGroup;
-import android.view.View;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.SoundEffectConstants;
+import android.R;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.util.AttributeSet;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.graphics.Bitmap;
-import android.os.SystemClock;
 import android.os.Handler;
 import android.os.Message;
-import android.R;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 
 /**
  * SlidingDrawer hides content out of the screen and allows the user to drag a handle
@@ -746,6 +747,8 @@
         openDrawer();
         invalidate();
         requestLayout();
+
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
     }
 
     /**
@@ -777,6 +780,7 @@
             scrollListener.onScrollStarted();
         }
         animateClose(mVertical ? mHandle.getTop() : mHandle.getLeft());
+
         if (scrollListener != null) {
             scrollListener.onScrollEnded();
         }
@@ -798,6 +802,9 @@
             scrollListener.onScrollStarted();
         }
         animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft());
+
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+
         if (scrollListener != null) {
             scrollListener.onScrollEnded();
         }
@@ -827,6 +834,7 @@
         }
 
         mExpanded = true;
+
         if (mOnDrawerOpenListener != null) {
             mOnDrawerOpenListener.onDrawerOpened();
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index adfc74f..219afec 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,6 +16,11 @@
 
 package android.widget;
 
+import com.android.internal.util.FastMath;
+import com.android.internal.widget.EditableInputConnection;
+
+import org.xmlpull.v1.XmlPullParserException;
+
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.ColorStateList;
@@ -31,17 +36,17 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
-import android.os.Message;
 import android.text.BoringLayout;
+import android.text.ClipboardManager;
 import android.text.DynamicLayout;
 import android.text.Editable;
 import android.text.GetChars;
 import android.text.GraphicsOperations;
-import android.text.ClipboardManager;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
@@ -49,9 +54,9 @@
 import android.text.Selection;
 import android.text.SpanWatcher;
 import android.text.Spannable;
+import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.SpannedString;
-import android.text.SpannableString;
 import android.text.StaticLayout;
 import android.text.TextPaint;
 import android.text.TextUtils;
@@ -64,19 +69,18 @@
 import android.text.method.LinkMovementMethod;
 import android.text.method.MetaKeyKeyListener;
 import android.text.method.MovementMethod;
-import android.text.method.TimeKeyListener;
-
 import android.text.method.PasswordTransformationMethod;
 import android.text.method.SingleLineTransformationMethod;
 import android.text.method.TextKeyListener;
+import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
 import android.text.style.ParagraphStyle;
 import android.text.style.URLSpan;
 import android.text.style.UpdateAppearance;
 import android.text.util.Linkify;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.FloatMath;
+import android.util.Log;
 import android.util.TypedValue;
 import android.view.ContextMenu;
 import android.view.Gravity;
@@ -89,25 +93,22 @@
 import android.view.ViewRoot;
 import android.view.ViewTreeObserver;
 import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
 import android.widget.RemoteViews.RemoteView;
 
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
-import com.android.internal.util.FastMath;
-import com.android.internal.widget.EditableInputConnection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 /**
  * Displays text to the user and optionally allows them to edit it.  A TextView
  * is a complete text editor, however the basic class is configured to not
@@ -6129,10 +6130,18 @@
 
     private class ChangeWatcher
     implements TextWatcher, SpanWatcher {
+
+        private CharSequence mBeforeText;
+
         public void beforeTextChanged(CharSequence buffer, int start,
                                       int before, int after) {
             if (DEBUG_EXTRACT) Log.v(TAG, "beforeTextChanged start=" + start
                     + " before=" + before + " after=" + after + ": " + buffer);
+
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                mBeforeText = buffer.toString();
+            }
+
             TextView.this.sendBeforeTextChanged(buffer, start, before, after);
         }
 
@@ -6141,6 +6150,13 @@
             if (DEBUG_EXTRACT) Log.v(TAG, "onTextChanged start=" + start
                     + " before=" + before + " after=" + after + ": " + buffer);
             TextView.this.handleTextChanged(buffer, start, before, after);
+
+            if (AccessibilityManager.getInstance(mContext).isEnabled() &&
+                    (isFocused() || isSelected() &&
+                    isShown())) {
+                sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
+                mBeforeText = null;
+            }
         }
 
         public void afterTextChanged(Editable buffer) {
@@ -6776,6 +6792,40 @@
     }
 
     @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean isPassword =
+            (mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION)) ==
+            (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
+
+        if (!isPassword) {
+            CharSequence text = getText();
+            if (TextUtils.isEmpty(text)) {
+                text = getHint();
+            }
+            if (!TextUtils.isEmpty(text)) {
+                if (text.length() > AccessibilityEvent.MAX_TEXT_LENGTH) {
+                    text = text.subSequence(0, AccessibilityEvent.MAX_TEXT_LENGTH + 1);
+                }
+                event.getText().add(text);
+            }
+        } else {
+            event.setPassword(isPassword);
+        }
+        return false;
+    }
+
+    void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
+            int fromIndex, int removedCount, int addedCount) {
+        AccessibilityEvent event =
+            AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+        event.setFromIndex(fromIndex);
+        event.setRemovedCount(removedCount);
+        event.setAddedCount(addedCount);
+        event.setBeforeText(beforeText);
+        sendAccessibilityEventUnchecked(event);
+    }
+
+    @Override
     protected void onCreateContextMenu(ContextMenu menu) {
         super.onCreateContextMenu(menu);
         boolean added = false;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index ff74787..670692f 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -21,8 +21,8 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
-import android.os.RemoteException;
 import android.os.Handler;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
 import android.view.Gravity;
@@ -278,7 +278,7 @@
         }
         tv.setText(s);
     }
-    
+
     // =======================================================================================
     // All the gunk below is the interaction with the Notification Service, which handles
     // the proper ordering of these system-wide.
@@ -373,6 +373,7 @@
                             TAG, "REMOVE! " + mView + " in " + this);
                     mWM.removeView(mView);
                 }
+
                 mView = null;
             }
         }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 633a831..43eec1b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1165,6 +1165,11 @@
              enabled for events such as long presses. -->
         <attr name="hapticFeedbackEnabled" format="boolean" />
 
+        <!-- Defines text that briefly describes content of the view. This property is used
+             primarily for accessibility. Since some views do not have textual
+             representation this attribute can be used for providing such. -->
+        <attr name="contentDescription" format="string" localization="suggested" />
+
         <!-- Name of the method in this View's context to invoke when the view is
              clicked. This name must correspond to a public method that takes
              exactly one parameter of type View. For instance, if you specify
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f90c6b8..b5808ea 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1100,6 +1100,7 @@
    <public type="attr" name="targetSdkVersion" id="0x01010270" />
    <public type="attr" name="maxSdkVersion" id="0x01010271" />
    <public type="attr" name="testOnly" id="0x01010272" />
+   <public type="attr" name="contentDescription" id="0x01010273" />
 
    <public type="anim" name="anticipate_interpolator" id="0x010a0007" />
    <public type="anim" name="overshoot_interpolator" id="0x010a0008" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 331ef1a..ed81cb4 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -887,7 +887,6 @@
         properties uploaded by the checkin service.  Not for use by normal
         applications.</string>
 
-
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindGadget">choose widgets</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2366,10 +2365,12 @@
 
     <!-- This string array should be overridden by the manufacture to present a list of carrier-id,locale pairs.  This is used at startup to set a default locale by checking the system property ro.carrier for the carrier-id and searching through this array -->
     <string-array translatable="false" name="carrier_locales">
-    </string-array>    
+    </string-array>
+
+     <!-- Title for the selected state of a CompoundButton. -->
+     <string name="accessibility_compound_button_selected">checked</string>
+
+     <!-- Title for the unselected state of a CompoundButton. -->
+     <string name="accessibility_compound_button_unselected">not checked</string>
+
 </resources>
-
-
-
-
-
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
new file mode 100644
index 0000000..c205fc0
--- /dev/null
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -0,0 +1,668 @@
+/*
+ ** Copyright 2009, 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 com.android.server;
+
+import static android.util.Config.LOGV;
+
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.HandlerCaller.SomeArgs;
+
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.accessibilityservice.IEventListener;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.text.TextUtils.SimpleStringSplitter;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.IAccessibilityManager;
+import android.view.accessibility.IAccessibilityManagerClient;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class is instantiated by the system as a system level service and can be
+ * accessed only by the system. The task of this service is to be a centralized
+ * event dispatch for {@link AccessibilityEvent}s generated across all processes
+ * on the device. Events are dispatched to {@link AccessibilityService}s.
+ *
+ * @hide
+ */
+public class AccessibilityManagerService extends IAccessibilityManager.Stub
+        implements HandlerCaller.Callback {
+
+    private static final String LOG_TAG = "AccessibilityManagerService";
+
+    private static int sIdCounter = 0;
+
+    private static final int OWN_PROCESS_ID = android.os.Process.myPid();
+
+    private static final int DO_SET_SERVICE_INFO = 10;
+
+    final HandlerCaller mCaller;
+
+    final Context mContext;
+
+    final Object mLock = new Object();
+
+    final List<Service> mServices = new ArrayList<Service>();
+
+    final List<IAccessibilityManagerClient> mClients =
+        new ArrayList<IAccessibilityManagerClient>();
+
+    final Map<ComponentName, Service> mComponentNameToServiceMap =
+        new HashMap<ComponentName, Service>();
+
+    private final List<ServiceInfo> mInstalledServices = new ArrayList<ServiceInfo>();
+
+    private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+
+    private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(':');
+
+    private PackageManager mPackageManager;
+
+    private int mHandledFeedbackTypes = 0;
+
+    private boolean mIsEnabled;
+
+    /**
+     * Handler for delayed event dispatch.
+     */
+    private Handler mHandler = new Handler() {
+
+        @Override
+        public void handleMessage(Message message) {
+            Service service = (Service) message.obj;
+            int eventType = message.arg1;
+
+            synchronized (mLock) {
+                notifyEventListenerLocked(service, eventType);
+                AccessibilityEvent oldEvent = service.mPendingEvents.get(eventType);
+                service.mPendingEvents.remove(eventType);
+                tryRecycleLocked(oldEvent);
+            }
+        }
+    };
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context A {@link Context} instance.
+     */
+    AccessibilityManagerService(Context context) {
+        mContext = context;
+        mPackageManager = mContext.getPackageManager();
+        mCaller = new HandlerCaller(context, this);
+
+        registerPackageChangeAndBootCompletedBroadcastReceiver();
+        registerSettingsContentObservers();
+
+        synchronized (mLock) {
+            populateAccessibilityServiceListLocked();
+        }
+    }
+
+    /**
+     * Registers a {@link BroadcastReceiver} for the events of
+     * adding/changing/removing/restarting a package and boot completion.
+     */
+    private void registerPackageChangeAndBootCompletedBroadcastReceiver() {
+        Context context = mContext;
+
+        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                synchronized (mLock) {
+                    populateAccessibilityServiceListLocked();
+                    manageServicesLocked();
+
+                    if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
+                        mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
+                        updateClientsLocked();
+                    }
+                }
+            }
+        };
+
+        // package changes
+        IntentFilter packageFilter = new IntentFilter();
+        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        packageFilter.addDataScheme("package");
+        context.registerReceiver(broadcastReceiver, packageFilter);
+
+        // boot completed
+        IntentFilter bootFiler = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+        mContext.registerReceiver(broadcastReceiver, bootFiler);
+    }
+
+    /**
+     * {@link ContentObserver}s for {@link Settings.Secure#ACCESSIBILITY_ENABLED}
+     * and {@link Settings.Secure#ENABLED_ACCESSIBILITY_SERVICES} settings.
+     */
+    private void registerSettingsContentObservers() {
+        ContentResolver contentResolver = mContext.getContentResolver();
+
+        Uri enabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED);
+        contentResolver.registerContentObserver(enabledUri, false,
+            new ContentObserver(new Handler()) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    super.onChange(selfChange);
+
+                    mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
+
+                    synchronized (mLock) {
+                        if (mIsEnabled) {
+                            manageServicesLocked();
+                        } else {
+                            unbindAllServicesLocked();
+                        }
+                        updateClientsLocked();
+                    }
+                }
+            });
+
+        Uri providersUri =
+            Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+        contentResolver.registerContentObserver(providersUri, false,
+            new ContentObserver(new Handler()) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    super.onChange(selfChange);
+
+                    synchronized (mLock) {
+                        manageServicesLocked();
+                    }
+                }
+            });
+    }
+
+    public void addClient(IAccessibilityManagerClient client) {
+        synchronized (mLock) {
+            try {
+                client.setEnabled(mIsEnabled);
+                mClients.add(client);
+            } catch (RemoteException re) {
+                Log.w(LOG_TAG, "Dead AccessibilityManagerClient: " + client, re);
+            }
+        }
+    }
+
+    public boolean sendAccessibilityEvent(AccessibilityEvent event) {
+        synchronized (mLock) {
+            notifyAccessibilityServicesDelayedLocked(event, false);
+            notifyAccessibilityServicesDelayedLocked(event, true);
+        }
+        // event not scheduled for dispatch => recycle
+        if (mHandledFeedbackTypes == 0) {
+            event.recycle();
+        } else {
+            mHandledFeedbackTypes = 0;
+        }
+
+        return (OWN_PROCESS_ID != Binder.getCallingPid());
+    }
+
+    public List<ServiceInfo> getAccessibilityServiceList() {
+        synchronized (mLock) {
+            return mInstalledServices;
+        }
+    }
+
+    public void interrupt() {
+        synchronized (mLock) {
+            for (int i = 0, count = mServices.size(); i < count; i++) {
+                Service service = mServices.get(i);
+                try {
+                    service.mServiceInterface.onInterrupt();
+                } catch (RemoteException re) {
+                    if (re instanceof DeadObjectException) {
+                        Log.w(LOG_TAG, "Dead " + service.mService + ". Cleaning up.");
+                        if (removeDeadServiceLocked(service)) {
+                            count--;
+                            i--;
+                        }
+                    } else {
+                        Log.e(LOG_TAG, "Error during sending interrupt request to "
+                                + service.mService, re);
+                    }
+                }
+            }
+        }
+    }
+
+    public void executeMessage(Message message) {
+        switch (message.what) {
+            case DO_SET_SERVICE_INFO:
+                SomeArgs arguments = ((SomeArgs) message.obj);
+
+                AccessibilityServiceInfo info = (AccessibilityServiceInfo) arguments.arg1;
+                Service service = (Service) arguments.arg2;
+
+                synchronized (mLock) {
+                    service.mEventTypes = info.eventTypes;
+                    service.mFeedbackType = info.feedbackType;
+                    String[] packageNames = info.packageNames;
+                    if (packageNames != null) {
+                        service.mPackageNames.addAll(Arrays.asList(packageNames));
+                    }
+                    service.mNotificationTimeout = info.notificationTimeout;
+                    service.mIsDefault = (info.flags & AccessibilityServiceInfo.DEFAULT) != 0;
+                }
+                return;
+            default:
+                Log.w(LOG_TAG, "Unknown message type: " + message.what);
+        }
+    }
+
+    /**
+     * Populates the cached list of installed {@link AccessibilityService}s.
+     */
+    private void populateAccessibilityServiceListLocked() {
+        mInstalledServices.clear();
+
+        List<ResolveInfo> installedServices = mPackageManager.queryIntentServices(
+                new Intent(AccessibilityService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
+
+        for (int i = 0, count = installedServices.size(); i < count; i++) {
+            mInstalledServices.add(installedServices.get(i).serviceInfo);
+        }
+    }
+
+    /**
+     * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
+     * and denotes the period after the last event before notifying the service.
+     *
+     * @param event The event.
+     * @param isDefault True to notify default listeners, not default services.
+     */
+    private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
+            boolean isDefault) {
+        for (int i = 0, count = mServices.size(); i < count; i++) {
+            Service service = mServices.get(i);
+
+            if (service.mIsDefault == isDefault) {
+                if (canDispathEventLocked(service, event, mHandledFeedbackTypes)) {
+                    mHandledFeedbackTypes |= service.mFeedbackType;
+                    notifyAccessibilityServiceDelayedLocked(service, event);
+                }
+            }
+        }
+    }
+
+    /**
+     * Performs an {@link AccessibilityService} delayed notification. The delay is configurable
+     * and denotes the period after the last event before notifying the service.
+     *
+     * @param service The service.
+     * @param event The event.
+     */
+    private void notifyAccessibilityServiceDelayedLocked(Service service,
+            AccessibilityEvent event) {
+        synchronized (mLock) {
+            int eventType = event.getEventType();
+            AccessibilityEvent oldEvent = service.mPendingEvents.get(eventType);
+            service.mPendingEvents.put(eventType, event);
+
+            int what = eventType | (service.mId << 16);
+            if (oldEvent != null) {
+                mHandler.removeMessages(what);
+                tryRecycleLocked(oldEvent);
+            }
+
+            Message message = mHandler.obtainMessage(what, service);
+            message.arg1 = event.getEventType();
+            mHandler.sendMessageDelayed(message, service.mNotificationTimeout);
+        }
+    }
+
+    /**
+     * Recycles an event if it can be safely recycled. The condition is that no
+     * not notified service is interested in the event.
+     *
+     * @param event The event.
+     */
+    private void tryRecycleLocked(AccessibilityEvent event) {
+        int eventType = event.getEventType();
+        List<Service> services = mServices;
+
+        // linear in the number of service which is not large
+        for (int i = 0, count = services.size(); i < count; i++) {
+            Service service = services.get(i);
+            if (service.mPendingEvents.get(eventType) == event) {
+                return;
+            }
+        }
+
+        event.recycle();
+    }
+
+    /**
+     * Notifies a service for a scheduled event given the event type.
+     *
+     * @param service The service.
+     * @param eventType The type of the event to dispatch.
+     */
+    private void notifyEventListenerLocked(Service service, int eventType) {
+        IEventListener listener = service.mServiceInterface;
+        AccessibilityEvent event = service.mPendingEvents.get(eventType);
+
+        try {
+            listener.onAccessibilityEvent(event);
+            if (LOGV) {
+                Log.i(LOG_TAG, "Event " + event + " sent to " + listener);
+            }
+        } catch (RemoteException re) {
+            if (re instanceof DeadObjectException) {
+                Log.w(LOG_TAG, "Dead " + service.mService + ". Cleaning up.");
+                synchronized (mLock) {
+                    removeDeadServiceLocked(service);
+                }
+            } else {
+                Log.e(LOG_TAG, "Error during sending " + event + " to " + service.mService, re);
+            }
+        }
+    }
+
+    /**
+     * Removes a dead service.
+     *
+     * @param service The service.
+     * @return True if the service was removed, false otherwise.
+     */
+    private boolean removeDeadServiceLocked(Service service) {
+        mServices.remove(service);
+        mHandler.removeMessages(service.mId);
+
+        if (LOGV) {
+            Log.i(LOG_TAG, "Dead service " + service.mService + " removed");
+        }
+
+        if (mServices.isEmpty()) {
+            mIsEnabled = false;
+            updateClientsLocked();
+        }
+
+        return true;
+    }
+
+    /**
+     * Determines if given event can be dispatched to a service based on the package of the
+     * event source and already notified services for that event type. Specifically, a
+     * service is notified if it is interested in events from the package and no other service
+     * providing the same feedback type has been notified. Exception are services the
+     * provide generic feedback (feedback type left as a safety net for unforeseen feedback
+     * types) which are always notified.
+     *
+     * @param service The potential receiver.
+     * @param event The event.
+     * @param handledFeedbackTypes The feedback types for which services have been notified.
+     * @return True if the listener should be notified, false otherwise.
+     */
+    private boolean canDispathEventLocked(Service service, AccessibilityEvent event,
+            int handledFeedbackTypes) {
+
+        if (!service.isConfigured()) {
+            return false;
+        }
+
+        if (!service.mService.isBinderAlive()) {
+            removeDeadServiceLocked(service);
+            return false;
+        }
+
+        int eventType = event.getEventType();
+        if ((service.mEventTypes & eventType) != eventType) {
+            return false;
+        }
+
+        Set<String> packageNames = service.mPackageNames;
+        CharSequence packageName = event.getPackageName();
+
+        if (packageNames.isEmpty() || packageNames.contains(packageName)) {
+            int feedbackType = service.mFeedbackType;
+            if ((handledFeedbackTypes & feedbackType) != feedbackType
+                    || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Manages services by starting enabled ones and stopping disabled ones.
+     */
+    private void manageServicesLocked() {
+        populateEnabledServicesLocked(mEnabledServices);
+        updateServicesStateLocked(mInstalledServices, mEnabledServices);
+    }
+
+    /**
+     * Unbinds all bound services.
+     */
+    private void unbindAllServicesLocked() {
+        List<Service> services = mServices;
+
+        for (int i = 0, count = services.size(); i < count; i++) {
+            Service service = services.get(i);
+
+            service.unbind();
+            mComponentNameToServiceMap.remove(service.mComponentName);
+        }
+        services.clear();
+    }
+
+    /**
+     * Populates a list with the {@link ComponentName}s of all enabled
+     * {@link AccessibilityService}s.
+     *
+     * @param enabledServices The list.
+     */
+    private void populateEnabledServicesLocked(Set<ComponentName> enabledServices) {
+        enabledServices.clear();
+
+        String servicesValue = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+
+        if (servicesValue != null) {
+            TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
+            splitter.setString(servicesValue);
+            while (splitter.hasNext()) {
+                ComponentName enabledService = ComponentName.unflattenFromString(splitter.next());
+                enabledServices.add(enabledService);
+            }
+        }
+    }
+
+    /**
+     * Updates the state of each service by starting (or keeping running) enabled ones and
+     * stopping the rest.
+     *
+     * @param installedServices All installed {@link AccessibilityService}s.
+     * @param enabledServices The {@link ComponentName}s of the enabled services.
+     */
+    private void updateServicesStateLocked(List<ServiceInfo> installedServices,
+            Set<ComponentName> enabledServices) {
+
+        Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
+        List<Service> services = mServices;
+
+        for (int i = 0, count = installedServices.size(); i < count; i++) {
+            ServiceInfo intalledService = installedServices.get(i);
+            ComponentName componentName = new ComponentName(intalledService.packageName,
+                    intalledService.name);
+            Service service = componentNameToServiceMap.get(componentName);
+
+            if (enabledServices.contains(componentName)) {
+                if (service == null) {
+                    new Service(componentName).bind();
+                }
+            } else {
+                if (service != null) {
+                    service.unbind();
+                    componentNameToServiceMap.remove(componentName);
+                    services.remove(service);
+                }
+            }
+        }
+    }
+
+    /**
+     * Updates the state of {@link android.view.accessibility.AccessibilityManager} clients.
+     */
+    private void updateClientsLocked() {
+        for (int i = 0, count = mClients.size(); i < count; i++) {
+            try {
+                mClients.get(i).setEnabled(mIsEnabled);
+            } catch (RemoteException re) {
+                mClients.remove(i);
+                count--;
+            }
+        }
+    }
+
+    /**
+     * This class represents an accessibility service. It stores all per service
+     * data required for the service management, provides API for starting/stopping the
+     * service and is responsible for adding/removing the service in the data structures
+     * for service management. The class also exposes configuration interface that is
+     * passed to the service it represents as soon it is bound. It also serves as the
+     * connection for the service.
+     */
+    class Service extends IAccessibilityServiceConnection.Stub implements ServiceConnection {
+        int mId = 0;
+
+        IBinder mService;
+
+        IEventListener mServiceInterface;
+
+        int mEventTypes;
+
+        int mFeedbackType;
+
+        Set<String> mPackageNames = new HashSet<String>();
+
+        boolean mIsDefault;
+
+        long mNotificationTimeout;
+
+        boolean mIsActive;
+
+        ComponentName mComponentName;
+
+        Intent mIntent;
+
+        // the events pending events to be dispatched to this service
+        final SparseArray<AccessibilityEvent> mPendingEvents =
+            new SparseArray<AccessibilityEvent>();
+
+        Service(ComponentName componentName) {
+            mId = sIdCounter++;
+            mComponentName = componentName;
+            mIntent = new Intent().setComponent(mComponentName);
+        }
+
+        /**
+         * Binds to the accessibility service.
+         */
+        public void bind() {
+            if (mService == null) {
+                mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
+            }
+        }
+
+        /**
+         * Unbinds form the accessibility service and removes it from the data
+         * structures for service management.
+         */
+        public void unbind() {
+            if (mService != null) {
+                mContext.unbindService(this);
+            }
+        }
+
+        /**
+         * Returns if the service is configured i.e. at least event types of interest
+         * and feedback type must be set.
+         *
+         * @return True if the service is configured, false otherwise.
+         */
+        public boolean isConfigured() {
+            return (mEventTypes != 0 && mFeedbackType != 0);
+        }
+
+        public void setServiceInfo(AccessibilityServiceInfo info) {
+            mCaller.obtainMessageOO(DO_SET_SERVICE_INFO, info, this).sendToTarget();
+        }
+
+        public void onServiceConnected(ComponentName componentName, IBinder service) {
+            mService = service;
+            mServiceInterface = IEventListener.Stub.asInterface(service);
+
+            try {
+                mServiceInterface.setConnection(this);
+                synchronized (mLock) {
+                    if (!mServices.contains(this)) {
+                        mServices.add(this);
+                        mComponentNameToServiceMap.put(componentName, this);
+                    }
+                }
+            } catch (RemoteException re) {
+                Log.w(LOG_TAG, "Error while setting Controller for service: " + service, re);
+            }
+        }
+
+        public void onServiceDisconnected(ComponentName componentName) {
+            synchronized (mLock) {
+                Service service = mComponentNameToServiceMap.remove(componentName);
+                mServices.remove(service);
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 6ed8b4c..4a2808b 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -16,6 +16,10 @@
 
 package com.android.server;
 
+import com.android.server.status.IconData;
+import com.android.server.status.NotificationData;
+import com.android.server.status.StatusBarService;
+
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
@@ -30,33 +34,29 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
-import android.media.AudioManager;
 import android.media.AsyncPlayer;
-import android.media.RingtoneManager;
+import android.media.AudioManager;
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Binder;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Power;
+import android.os.RemoteException;
 import android.os.Vibrator;
 import android.provider.Settings;
-import android.util.Config;
+import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
-import com.android.server.status.IconData;
-import com.android.server.status.NotificationData;
-import com.android.server.status.StatusBarService;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.io.IOException;
 
 class NotificationManagerService extends INotificationManager.Stub
 {
@@ -98,7 +98,7 @@
     private boolean mBatteryLow;
     private boolean mBatteryFull;
     private NotificationRecord mLedNotification;
-    
+
     private static final int BATTERY_LOW_ARGB = 0xFFFF0000; // Charging Low - red solid on
     private static final int BATTERY_MEDIUM_ARGB = 0xFFFFFF00;    // Charging - orange solid on
     private static final int BATTERY_FULL_ARGB = 0xFF00FF00; // Charging Full - green solid on
@@ -594,6 +594,9 @@
                         Binder.restoreCallingIdentity(identity);
                     }
                 }
+
+                sendAccessibilityEventTypeNotificationChangedDoCheck(notification, pkg);
+
             } else {
                 if (old != null && old.statusBarKey != null) {
                     long identity = Binder.clearCallingIdentity();
@@ -676,6 +679,26 @@
         idOut[0] = id;
     }
 
+    private void sendAccessibilityEventTypeNotificationChangedDoCheck(Notification notification,
+            CharSequence packageName) {
+        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+        if (!manager.isEnabled()) {
+            return;
+        }
+
+        AccessibilityEvent event =
+            AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
+        event.setPackageName(packageName);
+        event.setClassName(Notification.class.getName());
+        event.setParcelableData(notification);
+        CharSequence tickerText = notification.tickerText;
+        if (!TextUtils.isEmpty(tickerText)) {
+            event.getText().add(tickerText);
+        }
+
+        manager.sendAccessibilityEvent(event);
+    }
+
     private void cancelNotificationLocked(NotificationRecord r) {
         // status bar
         if (r.notification.icon != 0) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8b7260b..f6c1525 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -228,6 +228,14 @@
             }
 
             try {
+              Log.i(TAG, "Starting Accessibility Manager.");
+              ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
+                      new AccessibilityManagerService(context));
+            } catch (Throwable e) {
+              Log.e(TAG, "Failure starting Accessibility Manager", e);
+            }
+
+            try {
                 Log.i(TAG, "Starting Notification Manager.");
                 ServiceManager.addService(Context.NOTIFICATION_SERVICE,
                         new NotificationManagerService(context, statusBar, hardware));
diff --git a/tests/FrameworkTest/AndroidManifest.xml b/tests/FrameworkTest/AndroidManifest.xml
index c70302b..4e4ebffc 100644
--- a/tests/FrameworkTest/AndroidManifest.xml
+++ b/tests/FrameworkTest/AndroidManifest.xml
@@ -20,6 +20,9 @@
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.HARDWARE_TEST" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.ACCESSIBILITY_EVENT_VIEW_TYPES" />
+    <uses-permission android:name="android.permission.ACCESSIBILITY_EVENT_TRANSITION_TYPES" />
+    <uses-permission android:name="android.permission.ACCESSIBILITY_EVENT_NOTIFICATION_TYPES" />
 
     <application android:theme="@style/Theme">
         <uses-library android:name="android.test.runner" />
@@ -939,7 +942,7 @@
             </intent-filter>
         </activity>
         
-        <activity android:name="android.widget.AutoCompleteTextViewSimple" 
+        <activity android:name="android.widget.AutoCompleteTextViewSimple"
                   android:label="AutoCompleteTextViewSimple">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -947,6 +950,12 @@
             </intent-filter>
         </activity>
 
+        <service android:name=".accessibility.AccessibilityTestService">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" />
+            </intent-filter>
+        </service>
+
     </application>
 
 </manifest>
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/accessibility/AccessibilityTestService.java b/tests/FrameworkTest/src/com/android/frameworktest/accessibility/AccessibilityTestService.java
new file mode 100644
index 0000000..83d6056
--- /dev/null
+++ b/tests/FrameworkTest/src/com/android/frameworktest/accessibility/AccessibilityTestService.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2009 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 com.android.frameworktest.accessibility;
+
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Notification;
+import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * This class text the accessibility framework end to end.
+ * <p>
+ * Note: Since accessibility is provided by {@link AccessibilityService}s we create one,
+ * and it generates an event and an interruption dispatching them through the
+ * {@link AccessibilityManager}. We verify the received result. To trigger the test
+ * go to Settings->Accessibility and select the enable accessibility check and then
+ * select the check for this service (same name as the class).
+ */
+public class AccessibilityTestService extends AccessibilityService {
+
+    private static final String LOG_TAG = "AccessibilityTestService";
+
+    private static final String CLASS_NAME = "foo.bar.baz.Test";
+    private static final String PACKAGE_NAME = "foo.bar.baz";
+    private static final String TEXT = "Some stuff";
+    private static final String BEFORE_TEXT = "Some other stuff";
+
+    private static final String CONTENT_DESCRIPTION = "Content description";
+
+    private static final int ITEM_COUNT = 10;
+    private static final int CURRENT_ITEM_INDEX = 1;
+    private static final int INTERRUPT_INVOCATION_TYPE = 0x00000200;
+
+    private static final int FROM_INDEX = 1;
+    private static final int ADDED_COUNT = 2;
+    private static final int REMOVED_COUNT = 1;
+
+    private static final int NOTIFICATION_TIMEOUT_MILLIS = 80;
+
+    private int mReceivedResult;
+
+    private Timer mTimer = new Timer();
+
+    @Override
+    public void onServiceConnected() {
+        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+        info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
+        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE;
+        info.notificationTimeout = NOTIFICATION_TIMEOUT_MILLIS;
+        info.flags &= AccessibilityServiceInfo.DEFAULT;
+        setServiceInfo(info);
+
+        // we need to wait until the system picks our configuration
+        // otherwise it will not notify us
+        mTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                try {
+                    testAccessibilityEventDispatching();
+                    testInterrupt();
+                } catch (Exception e) {
+                    Log.e(LOG_TAG, "Error in testing Accessibility feature", e);
+                }
+            }
+        }, 1000);
+    }
+
+    /**
+     * Check here if the event we received is actually the one we sent.
+     */
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+        assert(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED == event.getEventType());
+        assert(event != null);
+        assert(event.getEventTime() > 0);
+        assert(CLASS_NAME.equals(event.getClassName()));
+        assert(PACKAGE_NAME.equals(event.getPackageName()));
+        assert(1 == event.getText().size());
+        assert(TEXT.equals(event.getText().get(0)));
+        assert(BEFORE_TEXT.equals(event.getBeforeText()));
+        assert(event.isChecked());
+        assert(CONTENT_DESCRIPTION.equals(event.getContentDescription()));
+        assert(ITEM_COUNT == event.getItemCount());
+        assert(CURRENT_ITEM_INDEX == event.getCurrentItemIndex());
+        assert(event.isEnabled());
+        assert(event.isPassword());
+        assert(FROM_INDEX == event.getFromIndex());
+        assert(ADDED_COUNT == event.getAddedCount());
+        assert(REMOVED_COUNT == event.getRemovedCount());
+        assert(event.getParcelableData() != null);
+        assert(1 == ((Notification) event.getParcelableData()).icon);
+
+        // set the type of the receved request
+        mReceivedResult = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
+    }
+
+    /**
+     * Set a flag that we received the interrupt request.
+     */
+    @Override
+    public void onInterrupt() {
+
+        // set the type of the receved request
+        mReceivedResult = INTERRUPT_INVOCATION_TYPE;
+    }
+
+    /**
+     * If an {@link AccessibilityEvent} is sent and received correctly.
+     */
+   public void testAccessibilityEventDispatching() throws Exception {
+       AccessibilityEvent event =
+           AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
+
+       assert(event != null);
+       event.setClassName(CLASS_NAME);
+       event.setPackageName(PACKAGE_NAME);
+       event.getText().add(TEXT);
+       event.setBeforeText(BEFORE_TEXT);
+       event.setChecked(true);
+       event.setContentDescription(CONTENT_DESCRIPTION);
+       event.setItemCount(ITEM_COUNT);
+       event.setCurrentItemIndex(CURRENT_ITEM_INDEX);
+       event.setEnabled(true);
+       event.setPassword(true);
+       event.setFromIndex(FROM_INDEX);
+       event.setAddedCount(ADDED_COUNT);
+       event.setRemovedCount(REMOVED_COUNT);
+       event.setParcelableData(new Notification(1, "Foo", 1234));
+
+       AccessibilityManager.getInstance(this).sendAccessibilityEvent(event);
+
+       assert(mReceivedResult == event.getEventType());
+
+       Log.i(LOG_TAG, "AccessibilityTestService#testAccessibilityEventDispatching: Success");
+   }
+
+   /**
+    * If accessibility feedback interruption is triggered and received correctly.
+    */
+   public void testInterrupt() throws Exception {
+       AccessibilityManager.getInstance(this).interrupt();
+
+       assert(INTERRUPT_INVOCATION_TYPE == mReceivedResult);
+
+       Log.i(LOG_TAG, "AccessibilityTestService#testInterrupt: Success");
+   }
+}
+
diff --git a/tests/FrameworkTest/tests/src/com/android/frameworktest/accessibility/RecycleAccessibilityEventTest.java b/tests/FrameworkTest/tests/src/com/android/frameworktest/accessibility/RecycleAccessibilityEventTest.java
new file mode 100644
index 0000000..d6380f9
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/com/android/frameworktest/accessibility/RecycleAccessibilityEventTest.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (C) 2009 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 com.android.frameworktest.accessibility;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.accessibility.AccessibilityEvent;
+
+import junit.framework.TestCase;
+
+/**
+ * This class exercises the caching and recycling of {@link AccessibilityEvent}s.
+ */
+public class RecycleAccessibilityEventTest extends TestCase {
+
+    private static final String CLASS_NAME = "foo.bar.baz.Test";
+    private static final String PACKAGE_NAME = "foo.bar.baz";
+    private static final String TEXT = "Some stuff";
+
+    private static final String CONTENT_DESCRIPTION = "Content description";
+    private static final int ITEM_COUNT = 10;
+    private static final int CURRENT_ITEM_INDEX = 1;
+
+    private static final int FROM_INDEX = 1;
+    private static final int ADDED_COUNT = 2;
+    private static final int REMOVED_COUNT = 1;
+
+    /**
+     * If an {@link AccessibilityEvent} is marshaled/unmarshaled correctly
+     */
+    @MediumTest
+    public void testAccessibilityEventViewTextChangedType() {
+        AccessibilityEvent first =
+            AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+        assertNotNull(first);
+
+        first.setClassName(CLASS_NAME);
+        first.setPackageName(PACKAGE_NAME);
+        first.getText().add(TEXT);
+        first.setFromIndex(FROM_INDEX);
+        first.setAddedCount(ADDED_COUNT);
+        first.setRemovedCount(REMOVED_COUNT);
+        first.setChecked(true);
+        first.setContentDescription(CONTENT_DESCRIPTION);
+        first.setItemCount(ITEM_COUNT);
+        first.setCurrentItemIndex(CURRENT_ITEM_INDEX);
+        first.setEnabled(true);
+        first.setPassword(true);
+
+        first.recycle();
+
+        assertNotNull(first);
+        assertNull(first.getClassName());
+        assertNull(first.getPackageName());
+        assertEquals(0, first.getText().size());
+        assertFalse(first.isChecked());
+        assertNull(first.getContentDescription());
+        assertEquals(0, first.getItemCount());
+        assertEquals(AccessibilityEvent.INVALID_POSITION, first.getCurrentItemIndex());
+        assertFalse(first.isEnabled());
+        assertFalse(first.isPassword());
+        assertEquals(0, first.getFromIndex());
+        assertEquals(0, first.getAddedCount());
+        assertEquals(0, first.getRemovedCount());
+
+        // get another event from the pool (this must be the recycled first)
+        AccessibilityEvent second = AccessibilityEvent.obtain();
+        assertEquals(first, second);
+    }
+}