Accessibility feature - framework changes (replacing 698, 699, 700, 701 and merging with the latest Donut)
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>
-
-
-
-
-