Merge "Add body id to ssl_certificate layout"
diff --git a/api/current.txt b/api/current.txt
index f21a4f3..309e747 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3371,6 +3371,7 @@
     method public void send(android.content.Context, int, android.content.Intent) throws android.app.PendingIntent.CanceledException;
     method public void send(int, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
     method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
+    method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String) throws android.app.PendingIntent.CanceledException;
     method public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -5297,6 +5298,7 @@
     method public java.lang.String getTargetPackage();
     method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
     method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
+    method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
     method public static void writeIntentSenderOrNullToParcel(android.content.IntentSender, android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -22395,6 +22397,7 @@
     method public void requestDisallowInterceptTouchEvent(boolean);
     method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public void requestTransparentRegion(android.view.View);
+    method protected void resetLayoutDirectionResolution();
     method public void scheduleLayoutAnimation();
     method public void setAddStatesFromChildren(boolean);
     method public void setAlwaysDrawnWithCacheEnabled(boolean);
@@ -26063,6 +26066,7 @@
     method protected void onTextChanged(java.lang.CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
+    method protected void resetLayoutDirectionResolution();
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 164acbc..68c9926 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -31,82 +31,151 @@
  * 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.
+ * etc. Such a service can optionally request the capability for querying the content
+ * of the active window. Development of an accessibility service requires extends this
+ * class and implements its abstract methods.
  * <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>
- * &nbsp;&nbsp;&lt;intent-filter&gt;<br>
- * &nbsp;&nbsp;&nbsp;&nbsp;&lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;<br>
- * &nbsp;&nbsp;&lt;/intent-filter&gt;<br>
- * &lt;/service&gt;<br>
- * </code>
+ * <strong>Lifecycle</strong>
  * </p>
  * <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
+ * The lifecycle of an accessibility service is managed exclusively by the system and
+ * follows the established service life cycle. Additionally, starting or stopping an
+ * accessibility service is triggered exclusively 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.
  * </p>
  * <p>
+ * <strong>Declaration</strong>
+ * </p>
+ * <p>
+ * An accessibility 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}. Failure to declare this intent will cause the system to
+ * ignore the accessibility service. Following is an example declaration:
+ * </p>
+ * <p>
+ * <code>
+ * <pre>
+ *   &lt;service android:name=".MyAccessibilityService"&gt;
+ *     &lt;intent-filter&gt;
+ *       &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
+ *     &lt;/intent-filter&gt;
+ *     . . .
+ *   &lt;/service&gt;
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Configuration</strong>
+ * </p>
+ * <p>
  * An accessibility service can be configured to receive specific types of accessibility events,
  * listen only to specific packages, get events from each type only once in a given time frame,
  * retrieve window content, specify a settings activity, etc.
  * </p>
+ * <p>
  * There are two approaches for configuring an accessibility service:
+ * </p>
  * <ul>
- *   <li>
- *     Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
- *     the service. A service declaration with a meta-data tag is presented below:
- *     <p>
- *       <code>
- *         &lt;service android:name=".MyAccessibilityService"&gt;<br>
- *         &nbsp;&nbsp;&lt;intent-filter&gt;<br>
- *         &nbsp;&nbsp;&nbsp;&nbsp;&lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;<br>
- *         &nbsp;&nbsp;&lt;/intent-filter&gt;<br>
- *         &nbsp;&nbsp;&lt;meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" /&gt;<br>
- *         &lt;/service&gt;<br>
- *       </code>
- *     </p>
- *     <p>
- *     <strong>
- *       This approach enables setting all accessibility service properties.
- *     </strong>
- *     </p>
- *     <p>
- *       For more details refer to {@link #SERVICE_META_DATA}.
- *     </p>
- *   </li>
- *   <li>
- *     Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
- *     that this method can be called any time to change the service configuration.<br>
- *     <p>
- *     <strong>
- *       This approach enables setting only dynamically configurable accessibility
- *       service properties:
- *       {@link AccessibilityServiceInfo#eventTypes},
- *       {@link AccessibilityServiceInfo#feedbackType},
- *       {@link AccessibilityServiceInfo#flags},
- *       {@link AccessibilityServiceInfo#notificationTimeout},
- *       {@link AccessibilityServiceInfo#packageNames}
- *     </strong>
- *     </p>
- *     <p>
- *       For more details refer to {@link AccessibilityServiceInfo}.
- *     </p>
- *   </li>
+ * <li>
+ * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
+ * the service. A service declaration with a meta-data tag is presented below:
+ * <p>
+ * <code>
+ * <pre>
+ *   &lt;service android:name=".MyAccessibilityService"&gt;
+ *     &lt;intent-filter&gt;
+ *       &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
+ *     &lt;/intent-filter&gt;
+ *     &lt;meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" /&gt;
+ *   &lt;/service&gt;
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Note:</strong>This approach enables setting all properties.
+ * </p>
+ * <p>
+ * For more details refer to {@link #SERVICE_META_DATA} and
+ * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>..
+ * </p>
+ * </li>
+ * <li>
+ * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
+ * that this method can be called any time to dynamically change the service configuration.
+ * <p>
+ * <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
+ * {@link AccessibilityServiceInfo#eventTypes},
+ * {@link AccessibilityServiceInfo#feedbackType},
+ * {@link AccessibilityServiceInfo#flags},
+ * {@link AccessibilityServiceInfo#notificationTimeout},
+ * {@link AccessibilityServiceInfo#packageNames}
+ * </p>
+ * <p>
+ * For more details refer to {@link AccessibilityServiceInfo}.
+ * </p>
+ * </li>
  * </ul>
  * <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.
+ * <strong>Retrieving window content</strong>
+ * </p>
+ * <p>
+ * An service can specify in its declaration that it can retrieve the active window
+ * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
+ * declaring this capability requires that the service declares its configuration via
+ * an XML resource referenced by {@link #SERVICE_META_DATA}.
+ * </p>
+ * <p>
+ * For security purposes an accessibility service can retrieve only the content of the
+ * currently active window. The currently active window is defined as the window from
+ * which was fired the last event of the following types:
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START},
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END},
+ * {@link AccessibilityEvent#TYPE_VIEW_CLICKED},
+ * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED},
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
+ * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED},
+ * {@link AccessibilityEvent#TYPE_VIEW_SELECTED},
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED},
+ * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED},
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED},
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}.
+ * In other words, the active window is the one where the user interaction is taking place.
+ * </p>
+ * <p>
+ * The entry point for retrieving window content is through calling
+ * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received
+ * event of the above types or a previous event from the same window
+ * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking
+ * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
+ * window content which represented as a tree of such objects.
+ * </p>
+ * <p>
+ * <strong>Note</strong>An accessibility service may have requested to be notified for
+ * a subset of the event types, thus be unaware that the active window has changed. Therefore
+ * accessibility service that would like to retrieve window content should:
+ * <ul>
+ * <li>
+ * Register for all event types with no notification timeout and keep track for the active
+ * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and
+ * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval
+ * methods on the latter.
+ * </li>
+ * <li>
+ * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
+ * active window has changed and the service did not get the accessibility event yet. Note
+ * that it is possible to have a retrieval method failing event adopting the strategy
+ * specified in the previous bullet because the accessibility event dispatch is asynchronous
+ * and crosses process boundaries.
+ * </li>
+ * </ul>
+ * </p>
  * <p>
  * <b>Notification strategy</b>
+ * </p>
  * <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
@@ -117,9 +186,10 @@
  * 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>
  * <p>
  * <b>Event types</b>
- * <p>
+ * </p>
  * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}
  * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
  * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
@@ -127,9 +197,16 @@
  * {@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 AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
+ * <p>
+ * <b>Feedback types</b>
+ * <p>
  * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
  * {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
  * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
@@ -140,10 +217,10 @@
  * @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.
+ * <strong>Note:</strong> 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 {
     /**
@@ -154,57 +231,25 @@
 
     /**
      * Name under which an AccessibilityService component publishes information
-     * about itself. This meta-data must reference an XML resource containing
-     * an
+     * about itself. This meta-data must reference an XML resource containing an
      * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>
      * tag. This is a a sample XML file configuring an accessibility service:
      * <p>
      * <code>
-     *   &lt;?xml version="1.0" encoding="utf-8"?&gt;<br>
-     *   &lt;accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"<br>
-     *   &nbsp;&nbsp;android:accessibilityEventTypes="typeViewClicked|typeViewFocused"<br>
-     *   &nbsp;&nbsp;android:packageNames="foo.bar, foo.baz"<br>
-     *   &nbsp;&nbsp;android:accessibilityFeedbackType="feedbackSpoken"<br>
-     *   &nbsp;&nbsp;android:notificationTimeout="100"<br>
-     *   &nbsp;&nbsp;android:accessibilityFlags="flagDefault"<br>
-     *   &nbsp;&nbsp;android:settingsActivity="foo.bar.TestBackActivity"<br>
-     *   &nbsp;&nbsp;. . .<br>
+     * <pre>
+     *   &lt;accessibility-service
+     *     android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
+     *     android:packageNames="foo.bar, foo.baz"
+     *     android:accessibilityFeedbackType="feedbackSpoken"
+     *     android:notificationTimeout="100"
+     *     android:accessibilityFlags="flagDefault"
+     *     android:settingsActivity="foo.bar.TestBackActivity"
+     *     android:canRetrieveWindowContent="true"
+     *     . . .
      *   /&gt;
+     * </pre>
      * </code>
      * </p>
-     * <p>
-     *  <strong>Note:</strong> A service can retrieve only the content of the active window.
-     *          An active window is the source of the most recent event of type
-     *          {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START},
-     *          {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END},
-     *          {@link AccessibilityEvent#TYPE_VIEW_CLICKED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_FOCUSED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
-     *          {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
-     *          {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_SELECTED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED},
-     *          {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}.
-     *          Therefore the service should:
-     *          <ul>
-     *            <li>
-     *              Register for all event types with no notification timeout and keep track
-     *              for the active window by calling
-     *              {@link AccessibilityEvent#getWindowId()} of the last received
-     *              event and compare this with the
-     *              {@link AccessibilityNodeInfo#getWindowId()} before calling
-     *              retrieval methods on the latter.
-     *            </li>
-     *            <li>
-     *              Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail
-     *              since the active window has changed and the service did not get the 
-     *              accessibility event. Note that it is possible to have a retrieval method
-     *              failing event adopting the strategy specified in the previous bullet
-     *              because the accessibility event dispatch is asynchronous and crosses
-     *              process boundaries. 
-     *            </li>
-     *          <ul>
-     * </p>
      */
     public static final String SERVICE_META_DATA = "android.accessibilityservice";
 
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index b9878cd..ef4adca 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -37,13 +37,13 @@
 import java.io.IOException;
 
 /**
- * This class describes an {@link AccessibilityService}. The system
- * notifies an {@link AccessibilityService} for
- * {@link android.view.accessibility.AccessibilityEvent}s
+ * 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
+ * @see android.view.accessibility.AccessibilityManager
  */
 public class AccessibilityServiceInfo implements Parcelable {
 
@@ -93,12 +93,19 @@
      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
      */
     public int eventTypes;
 
     /**
      * The package names an {@link AccessibilityService} is interested in. Setting
-     * to null is equivalent to all packages.
+     * to <code>null</code> is equivalent to all packages.
      * <p>
      *   <strong>Can be dynamically set at runtime.</strong>
      * </p>
@@ -125,10 +132,10 @@
      *   <strong>Can be dynamically set at runtime.</strong>.
      * </p>
      * <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
+     * <strong>Note:</strong> 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;
 
@@ -159,7 +166,7 @@
     private String mSettingsActivityName;
 
     /**
-     * Flag whether this accessibility service can retrieve screen content.
+     * Flag whether this accessibility service can retrieve window content.
      */
     private boolean mCanRetrieveWindowContent;
 
@@ -296,12 +303,12 @@
     }
 
     /**
-     * Whether this service can retrieve the currently focused window content.
+     * Whether this service can retrieve the current window's content.
      * <p>
      *    <strong>Statically set from
      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
      * </p>
-     * @return True screen content is retrieved.
+     * @return True window content can be retrieved.
      */
     public boolean getCanRetrieveWindowContent() {
         return mCanRetrieveWindowContent;
diff --git a/core/java/android/accessibilityservice/package.html b/core/java/android/accessibilityservice/package.html
new file mode 100644
index 0000000..0c640d1
--- /dev/null
+++ b/core/java/android/accessibilityservice/package.html
@@ -0,0 +1,22 @@
+<html>
+<body>
+<p>
+  The classes in this package are used for development of accessibility service that
+  provide alternative or augmented feedback to the user.
+</p>
+<p>
+  An {@link android.accessibilityservice.AccessibilityService} runs in the background and
+  receives callbacks by the system when {@link android.view.accessibility.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. Such a service can optionally request the
+  capability for querying the content of the active window. Development of an accessibility
+  service requires extends this class and implements its abstract methods.
+</p>
+<p>
+  An {@link android.accessibilityservice.AccessibilityServiceInfo} describes an
+  {@link android.accessibilityservice.AccessibilityService}. The system notifies an
+  AccessibilityService for {@link android.view.accessibility.AccessibilityEvent}s
+  according to the information encapsulated in this class.
+</p>
+</body>
+</html>
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 85f40c9..fdf4a3a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -251,12 +251,13 @@
             IBinder b = data.readStrongBinder();
             IApplicationThread app =
                 b != null ? ApplicationThreadNative.asInterface(b) : null;
+            String packageName = data.readString();
             b = data.readStrongBinder();
             IIntentReceiver rec
                 = b != null ? IIntentReceiver.Stub.asInterface(b) : null;
             IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
             String perm = data.readString();
-            Intent intent = registerReceiver(app, rec, filter, perm);
+            Intent intent = registerReceiver(app, packageName, rec, filter, perm);
             reply.writeNoException();
             if (intent != null) {
                 reply.writeInt(1);
@@ -1503,6 +1504,16 @@
             return true;
         }
 
+        case IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender r = IIntentSender.Stub.asInterface(
+                data.readStrongBinder());
+            boolean res = isIntentSenderTargetedToPackage(r);
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1702,7 +1713,7 @@
         reply.recycle();
         return res;
     }
-    public Intent registerReceiver(IApplicationThread caller,
+    public Intent registerReceiver(IApplicationThread caller, String packageName,
             IIntentReceiver receiver,
             IntentFilter filter, String perm) throws RemoteException
     {
@@ -1710,6 +1721,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(caller != null ? caller.asBinder() : null);
+        data.writeString(packageName);
         data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
         filter.writeToParcel(data, 0);
         data.writeString(perm);
@@ -3385,5 +3397,18 @@
         reply.recycle();
     }
 
+    public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        mRemote.transact(IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean res = reply.readInt() != 0;
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 94a4afa..8749d3e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -61,7 +61,6 @@
 import android.net.wifi.WifiManager;
 import android.nfc.NfcManager;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.DropBoxManager;
 import android.os.Environment;
@@ -81,7 +80,6 @@
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
-import android.view.Display;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -142,6 +140,7 @@
             new HashMap<String, SharedPreferencesImpl>();
 
     /*package*/ LoadedApk mPackageInfo;
+    private String mBasePackageName;
     private Resources mResources;
     /*package*/ ActivityThread mMainThread;
     private Context mOuterContext;
@@ -1030,7 +1029,7 @@
         }
         try {
             return ActivityManagerNative.getDefault().registerReceiver(
-                    mMainThread.getApplicationThread(),
+                    mMainThread.getApplicationThread(), mBasePackageName,
                     rd, filter, broadcastPermission);
         } catch (RemoteException e) {
             return null;
@@ -1397,7 +1396,7 @@
         if (pi != null) {
             ContextImpl c = new ContextImpl();
             c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
-            c.init(pi, null, mMainThread, mResources);
+            c.init(pi, null, mMainThread, mResources, mBasePackageName);
             if (c.mResources != null) {
                 return c;
             }
@@ -1450,6 +1449,7 @@
      */
     public ContextImpl(ContextImpl context) {
         mPackageInfo = context.mPackageInfo;
+        mBasePackageName = context.mBasePackageName;
         mResources = context.mResources;
         mMainThread = context.mMainThread;
         mContentResolver = context.mContentResolver;
@@ -1458,13 +1458,14 @@
 
     final void init(LoadedApk packageInfo,
             IBinder activityToken, ActivityThread mainThread) {
-        init(packageInfo, activityToken, mainThread, null);
+        init(packageInfo, activityToken, mainThread, null, null);
     }
 
     final void init(LoadedApk packageInfo,
                 IBinder activityToken, ActivityThread mainThread,
-                Resources container) {
+                Resources container, String basePackageName) {
         mPackageInfo = packageInfo;
+        mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
         mResources = mPackageInfo.getResources(mainThread);
 
         if (mResources != null && container != null
@@ -1485,6 +1486,7 @@
 
     final void init(Resources resources, ActivityThread mainThread) {
         mPackageInfo = null;
+        mBasePackageName = null;
         mResources = resources;
         mMainThread = mainThread;
         mContentResolver = new ApplicationContentResolver(this, mainThread);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e2588cf..9e20764 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -103,7 +103,7 @@
             throws RemoteException;
     public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
     public boolean willActivityBeVisible(IBinder token) throws RemoteException;
-    public Intent registerReceiver(IApplicationThread caller,
+    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter,
             String requiredPermission) throws RemoteException;
     public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
@@ -361,6 +361,8 @@
     public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
     public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;
 
+    public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -587,4 +589,5 @@
     int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
     int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
     int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
+    int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134;
 }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 5b43b65..b4827cb 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -365,7 +365,7 @@
      * is no longer allowing more intents to be sent through it.
      */
     public void send() throws CanceledException {
-        send(null, 0, null, null, null);
+        send(null, 0, null, null, null, null);
     }
 
     /**
@@ -379,7 +379,7 @@
      * is no longer allowing more intents to be sent through it.
      */
     public void send(int code) throws CanceledException {
-        send(null, code, null, null, null);
+        send(null, code, null, null, null, null);
     }
 
     /**
@@ -399,7 +399,7 @@
      */
     public void send(Context context, int code, Intent intent)
             throws CanceledException {
-        send(context, code, intent, null, null);
+        send(context, code, intent, null, null, null);
     }
 
     /**
@@ -420,7 +420,7 @@
      */
     public void send(int code, OnFinished onFinished, Handler handler)
             throws CanceledException {
-        send(null, code, null, onFinished, handler);
+        send(null, code, null, onFinished, handler, null);
     }
 
     /**
@@ -449,20 +449,64 @@
      * @see #send(int)
      * @see #send(Context, int, Intent)
      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+     * @see #send(Context, int, Intent, OnFinished, Handler, String)
      *
      * @throws CanceledException Throws CanceledException if the PendingIntent
      * is no longer allowing more intents to be sent through it.
      */
     public void send(Context context, int code, Intent intent,
             OnFinished onFinished, Handler handler) throws CanceledException {
+        send(context, code, intent, onFinished, handler, null);
+    }
+
+    /**
+     * Perform the operation associated with this PendingIntent, allowing the
+     * caller to specify information about the Intent to use and be notified
+     * when the send has completed.
+     *
+     * <p>For the intent parameter, a PendingIntent
+     * often has restrictions on which fields can be supplied here, based on
+     * how the PendingIntent was retrieved in {@link #getActivity},
+     * {@link #getBroadcast}, or {@link #getService}.
+     *
+     * @param context The Context of the caller.  This may be null if
+     * <var>intent</var> is also null.
+     * @param code Result code to supply back to the PendingIntent's target.
+     * @param intent Additional Intent data.  See {@link Intent#fillIn
+     * Intent.fillIn()} for information on how this is applied to the
+     * original Intent.  Use null to not modify the original Intent.
+     * @param onFinished The object to call back on when the send has
+     * completed, or null for no callback.
+     * @param handler Handler identifying the thread on which the callback
+     * should happen.  If null, the callback will happen from the thread
+     * pool of the process.
+     * @param requiredPermission Name of permission that a recipient of the PendingIntent
+     * is required to hold.  This is only valid for broadcast intents, and
+     * corresponds to the permission argument in
+     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+     * If null, no permission is required.
+     *
+     * @see #send()
+     * @see #send(int)
+     * @see #send(Context, int, Intent)
+     * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+     * @see #send(Context, int, Intent, OnFinished, Handler)
+     *
+     * @throws CanceledException Throws CanceledException if the PendingIntent
+     * is no longer allowing more intents to be sent through it.
+     */
+    public void send(Context context, int code, Intent intent,
+            OnFinished onFinished, Handler handler, String requiredPermission)
+            throws CanceledException {
         try {
             String resolvedType = intent != null ?
                     intent.resolveTypeIfNeeded(context.getContentResolver())
                     : null;
             int res = mTarget.send(code, intent, resolvedType,
                     onFinished != null
-                    ? new FinishedDispatcher(this, onFinished, handler)
-                    : null);
+                            ? new FinishedDispatcher(this, onFinished, handler)
+                            : null,
+                    requiredPermission);
             if (res < 0) {
                 throw new CanceledException();
             }
@@ -491,6 +535,20 @@
     }
 
     /**
+     * @hide
+     * Check to verify that this PendingIntent targets a specific package.
+     */
+    public boolean isTargetedToPackage() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .isIntentSenderTargetedToPackage(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return false;
+        }
+    }
+
+    /**
      * Comparison operator on two PendingIntent objects, such that true
      * is returned then they both represent the same operation from the
      * same package.  This allows you to use {@link #getActivity},
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index aecec66..fed6d81 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1029,6 +1029,12 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
+     * registered with this method will correctly respect the
+     * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
+     * Prior to that, it would be ignored and delivered to all matching registered
+     * receivers.  Be careful if using this for security.</p>
+     *
      * <p class="note">Note: this method <em>cannot be called from a
      * {@link BroadcastReceiver} component;</em> that is, from a BroadcastReceiver
      * that is declared in an application's manifest.  It is okay, however, to call
@@ -1059,6 +1065,12 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
+     * registered with this method will correctly respect the
+     * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
+     * Prior to that, it would be ignored and delivered to all matching registered
+     * receivers.  Be careful if using this for security.</p>
+     *
      * @param receiver The BroadcastReceiver to handle the broadcast.
      * @param filter Selects the Intent broadcasts to be received.
      * @param broadcastPermission String naming a permissions that a
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
index b7da472..7dbd6f2 100644
--- a/core/java/android/content/IIntentSender.aidl
+++ b/core/java/android/content/IIntentSender.aidl
@@ -22,5 +22,5 @@
 /** @hide */
 interface IIntentSender {
     int send(int code, in Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver);
+            IIntentReceiver finishedReceiver, String requiredPermission);
 }
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 007a715..4db4bdc 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -154,14 +154,47 @@
      */
     public void sendIntent(Context context, int code, Intent intent,
             OnFinished onFinished, Handler handler) throws SendIntentException {
+        sendIntent(context, code, intent, onFinished, handler, null);
+    }
+
+    /**
+     * Perform the operation associated with this IntentSender, allowing the
+     * caller to specify information about the Intent to use and be notified
+     * when the send has completed.
+     *
+     * @param context The Context of the caller.  This may be null if
+     * <var>intent</var> is also null.
+     * @param code Result code to supply back to the IntentSender's target.
+     * @param intent Additional Intent data.  See {@link Intent#fillIn
+     * Intent.fillIn()} for information on how this is applied to the
+     * original Intent.  Use null to not modify the original Intent.
+     * @param onFinished The object to call back on when the send has
+     * completed, or null for no callback.
+     * @param handler Handler identifying the thread on which the callback
+     * should happen.  If null, the callback will happen from the thread
+     * pool of the process.
+     * @param requiredPermission Name of permission that a recipient of the PendingIntent
+     * is required to hold.  This is only valid for broadcast intents, and
+     * corresponds to the permission argument in
+     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+     * If null, no permission is required.
+     *
+     *
+     * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+     * is no longer allowing more intents to be sent through it.
+     */
+    public void sendIntent(Context context, int code, Intent intent,
+            OnFinished onFinished, Handler handler, String requiredPermission)
+            throws SendIntentException {
         try {
             String resolvedType = intent != null ?
                     intent.resolveTypeIfNeeded(context.getContentResolver())
                     : null;
             int res = mTarget.send(code, intent, resolvedType,
                     onFinished != null
-                    ? new FinishedDispatcher(this, onFinished, handler)
-                    : null);
+                            ? new FinishedDispatcher(this, onFinished, handler)
+                            : null,
+                    requiredPermission);
             if (res < 0) {
                 throw new SendIntentException();
             }
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 5ade9eb..0eb8cd8 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -338,7 +338,15 @@
      * @hide
      */
     public static NdefRecord createUri(Uri uri) {
-        String uriString = uri.toString();
+        return createUri(uri.toString());
+    }
+
+    /**
+     * Creates an NDEF record of well known type URI.
+     * TODO: Make a public API
+     * @hide
+     */
+    public static NdefRecord createUri(String uriString) {
         byte prefix = 0x0;
         for (int i = 1; i < URI_PREFIX_MAP.length; i++) {
             if (uriString.startsWith(URI_PREFIX_MAP[i])) {
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 3971045..b492615 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -17,9 +17,6 @@
 package android.provider;
 
 
-import com.android.internal.util.ArrayUtils;
-
-import android.accounts.Account;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.ContentProviderClient;
@@ -35,13 +32,10 @@
 import android.database.DatabaseUtils;
 import android.net.Uri;
 import android.os.RemoteException;
-import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.format.Time;
 import android.util.Log;
 
-import java.util.Arrays;
-
 /**
  * <p>
  * The contract between the calendar provider and applications. Contains
@@ -97,6 +91,8 @@
     /**
      * Broadcast Action: This is the intent that gets fired when an alarm
      * notification needs to be posted for a reminder.
+     *
+     * @SdkConstant
      */
     public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
 
@@ -122,8 +118,7 @@
     /**
      * The content:// style URL for the top-level calendar authority
      */
-    public static final Uri CONTENT_URI =
-        Uri.parse("content://" + AUTHORITY);
+    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
 
     /**
      * An optional insert, update or delete URI parameter that allows the caller
@@ -572,29 +567,6 @@
      * </ul>
      */
     public static class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
-        private static final String WHERE_DELETE_FOR_ACCOUNT = Calendars.ACCOUNT_NAME + "=?"
-                + " AND "
-                + Calendars.ACCOUNT_TYPE + "=?";
-
-        /**
-         * Helper function for generating a calendars query. This is blocking
-         * and should not be used on the UI thread. See
-         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
-         * for more details about using the parameters.
-         *
-         * @param cr The ContentResolver to query with
-         * @param projection A list of columns to return
-         * @param selection A formatted selection string
-         * @param selectionArgs arguments to the selection string
-         * @param orderBy How to order the returned rows
-         * @return
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection, String selection,
-                String[] selectionArgs, String orderBy) {
-            return cr.query(CONTENT_URI, projection, selection, selectionArgs,
-                    orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-        }
-
         /**
          * The content:// style URL for accessing Calendars
          */
@@ -622,7 +594,9 @@
          * These fields are only writable by a sync adapter. To modify them the
          * caller must include {@link #CALLER_IS_SYNCADAPTER},
          * {@link #ACCOUNT_NAME}, and {@link #ACCOUNT_TYPE} in the Uri's query
-         * parameters.
+         * parameters. TODO move to provider
+         *
+         * @hide
          */
         public static final String[] SYNC_WRITABLE_COLUMNS = new String[] {
             ACCOUNT_NAME,
@@ -737,7 +711,7 @@
         /**
          * the projection used by the attendees query
          */
-        private static final String[] PROJECTION = new String[] {
+        public static final String[] PROJECTION = new String[] {
                 _ID, ATTENDEE_NAME, ATTENDEE_EMAIL, ATTENDEE_RELATIONSHIP, ATTENDEE_STATUS,};
         private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
 
@@ -1420,37 +1394,6 @@
             CalendarColumns {
 
         /**
-         * Queries all events with the given projection. This is a blocking call
-         * and should not be done on the UI thread.
-         *
-         * @param cr The content resolver to use for the query
-         * @param projection The columns to return
-         * @return A Cursor containing all events in the db
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection) {
-            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
-        }
-
-        /**
-         * Queries events using the given projection, selection filter, and
-         * ordering. This is a blocking call and should not be done on the UI
-         * thread. For selection and selectionArgs usage see
-         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
-         *
-         * @param cr The content resolver to use for the query
-         * @param projection The columns to return
-         * @param selection Filter on the query as an SQL WHERE statement
-         * @param selectionArgs Args to replace any '?'s in the selection
-         * @param orderBy How to order the rows as an SQL ORDER BY statement
-         * @return A Cursor containing the matching events
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection, String selection,
-                String[] selectionArgs, String orderBy) {
-            return cr.query(CONTENT_URI, projection, selection, null,
-                    orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-        }
-
-        /**
          * The content:// style URL for interacting with events. Appending an
          * event id using {@link ContentUris#withAppendedId(Uri, long)} will
          * specify a single event.
@@ -1464,7 +1407,7 @@
          * appended event ID.  Deletion of exceptions requires both the original event ID and
          * the exception event ID (see {@link Uri.Builder#appendPath}).
          */
-        public static final Uri EXCEPTION_CONTENT_URI =
+        public static final Uri CONTENT_EXCEPTION_URI =
                 Uri.parse("content://" + AUTHORITY + "/exception");
 
         /**
@@ -1475,7 +1418,9 @@
         /**
          * These are columns that should only ever be updated by the provider,
          * either because they are views mapped to another table or because they
-         * are used for provider only functionality.
+         * are used for provider only functionality. TODO move to provider
+         *
+         * @hide
          */
         public static String[] PROVIDER_WRITABLE_COLUMNS = new String[] {
                 ACCOUNT_NAME,
@@ -1505,7 +1450,9 @@
         /**
          * These fields are only writable by a sync adapter. To modify them the
          * caller must include CALLER_IS_SYNCADAPTER, _SYNC_ACCOUNT, and
-         * _SYNC_ACCOUNT_TYPE in the query parameters.
+         * _SYNC_ACCOUNT_TYPE in the query parameters. TODO move to provider.
+         *
+         * @hide
          */
         public static final String[] SYNC_WRITABLE_COLUMNS = new String[] {
             _SYNC_ID,
@@ -1672,11 +1619,6 @@
         public static final String END_MINUTE = "endMinute";
     }
 
-    /**
-     * CalendarCache stores some settings for calendar including the current
-     * time zone for the instaces. These settings are stored using a key/value
-     * scheme.
-     */
     protected interface CalendarCacheColumns {
         /**
          * The key for the setting. Keys are defined in {@link CalendarCache}.
@@ -1689,6 +1631,11 @@
         public static final String VALUE = "value";
     }
 
+    /**
+     * CalendarCache stores some settings for calendar including the current
+     * time zone for the instances. These settings are stored using a key/value
+     * scheme. A {@link #KEY} must be specified when updating these values.
+     */
     public static class CalendarCache implements CalendarCacheColumns {
         /**
          * The URI to use for retrieving the properties from the Calendar db.
@@ -1697,22 +1644,11 @@
                 Uri.parse("content://" + AUTHORITY + "/properties");
 
         /**
-         * If updating a property, this must be provided as the selection. All
-         * other selections will fail. For queries this field can be omitted to
-         * retrieve all properties or used to query a single property. Valid
-         * keys include {@link #TIMEZONE_KEY_TYPE},
-         * {@link #TIMEZONE_KEY_INSTANCES}, and
-         * {@link #TIMEZONE_KEY_INSTANCES_PREVIOUS}, though the last one can
-         * only be read, not written.
-         */
-        public static final String WHERE = "key=?";
-
-        /**
          * They key for updating the use of auto/home time zones in Calendar.
          * Valid values are {@link #TIMEZONE_TYPE_AUTO} or
          * {@link #TIMEZONE_TYPE_HOME}.
          */
-        public static final String TIMEZONE_KEY_TYPE = "timezoneType";
+        public static final String KEY_TIMEZONE_TYPE = "timezoneType";
 
         /**
          * The key for updating the time zone used by the provider when it
@@ -1720,24 +1656,24 @@
          * type is set to {@link #TIMEZONE_TYPE_HOME}. A valid time zone id
          * should be written to this field.
          */
-        public static final String TIMEZONE_KEY_INSTANCES = "timezoneInstances";
+        public static final String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
 
         /**
          * The key for reading the last time zone set by the user. This should
          * only be read by apps and it will be automatically updated whenever
-         * {@link #TIMEZONE_KEY_INSTANCES} is updated with
+         * {@link #KEY_TIMEZONE_INSTANCES} is updated with
          * {@link #TIMEZONE_TYPE_HOME} set.
          */
-        public static final String TIMEZONE_KEY_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+        public static final String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
 
         /**
-         * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+         * The value to write to {@link #KEY_TIMEZONE_TYPE} if the provider
          * should stay in sync with the device's time zone.
          */
         public static final String TIMEZONE_TYPE_AUTO = "auto";
 
         /**
-         * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+         * The value to write to {@link #KEY_TIMEZONE_TYPE} if the provider
          * should use a fixed time zone set by the user.
          */
         public static final String TIMEZONE_TYPE_HOME = "home";
@@ -1814,7 +1750,7 @@
         /**
          * The projection used by the EventDays query.
          */
-        private static final String[] PROJECTION = {
+        public static final String[] PROJECTION = {
                 STARTDAY, ENDDAY
         };
         private static final String SELECTION = "selected=1";
@@ -1900,7 +1836,7 @@
         /**
          * The projection used by the reminders query.
          */
-        private static final String[] PROJECTION = new String[] {
+        public static final String[] PROJECTION = new String[] {
                 _ID, MINUTES, METHOD,};
         @SuppressWarnings("hiding")
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/reminders");
@@ -1967,17 +1903,28 @@
         public static final String NOTIFY_TIME = "notifyTime";
 
         /**
-         * The state of this alert. It starts out as {@link #SCHEDULED}, then
-         * when the alarm goes off, it changes to {@link #FIRED}, and then when
-         * the user dismisses the alarm it changes to {@link #DISMISSED}. Column
+         * The state of this alert. It starts out as {@link #STATE_SCHEDULED}, then
+         * when the alarm goes off, it changes to {@link #STATE_FIRED}, and then when
+         * the user dismisses the alarm it changes to {@link #STATE_DISMISSED}. Column
          * name.
          * <P>Type: INTEGER</P>
          */
         public static final String STATE = "state";
 
-        public static final int SCHEDULED = 0;
-        public static final int FIRED = 1;
-        public static final int DISMISSED = 2;
+        /**
+         * An alert begins in this state when it is first created.
+         */
+        public static final int STATE_SCHEDULED = 0;
+        /**
+         * After a notification for an alert has been created it should be
+         * updated to fired.
+         */
+        public static final int STATE_FIRED = 1;
+        /**
+         * Once the user has dismissed the notification the alert's state should
+         * be set to dismissed so it is not fired again.
+         */
+        public static final int STATE_DISMISSED = 2;
 
         /**
          * The number of minutes that this alarm precedes the start time. Column
@@ -2024,7 +1971,7 @@
         private static final String WHERE_FINDNEXTALARMTIME = ALARM_TIME + ">=?";
         private static final String SORT_ORDER_ALARMTIME_ASC = ALARM_TIME + " ASC";
 
-        private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + SCHEDULED
+        private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + STATE_SCHEDULED
                 + " AND " + ALARM_TIME + "<?"
                 + " AND " + ALARM_TIME + ">?"
                 + " AND " + END + ">=?";
@@ -2038,10 +1985,11 @@
         public static final Uri CONTENT_URI_BY_INSTANCE =
             Uri.parse("content://" + AUTHORITY + "/calendar_alerts/by_instance");
 
-        private static final boolean DEBUG = true;
+        private static final boolean DEBUG = false;
 
         /**
-         * Helper for inserting an alarm time associated with an event
+         * Helper for inserting an alarm time associated with an event TODO move
+         * to Provider
          *
          * @hide
          */
@@ -2056,51 +2004,32 @@
             values.put(CalendarAlerts.CREATION_TIME, currentTime);
             values.put(CalendarAlerts.RECEIVED_TIME, 0);
             values.put(CalendarAlerts.NOTIFY_TIME, 0);
-            values.put(CalendarAlerts.STATE, SCHEDULED);
+            values.put(CalendarAlerts.STATE, STATE_SCHEDULED);
             values.put(CalendarAlerts.MINUTES, minutes);
             return cr.insert(CONTENT_URI, values);
         }
 
         /**
-         * Queries alerts info using the given projection, selection filter, and
-         * ordering. This is a blocking call and should not be done on the UI
-         * thread. For selection and selectionArgs usage see
-         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
-         *
-         * @param cr The content resolver to use for the query
-         * @param projection The columns to return
-         * @param selection Filter on the query as an SQL WHERE statement
-         * @param selectionArgs Args to replace any '?'s in the selection
-         * @param sortOrder How to order the rows as an SQL ORDER BY statement
-         * @return A Cursor containing the matching alerts
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection,
-                String selection, String[] selectionArgs, String sortOrder) {
-            return cr.query(CONTENT_URI, projection, selection, selectionArgs,
-                    sortOrder);
-        }
-
-        /**
          * Finds the next alarm after (or equal to) the given time and returns
          * the time of that alarm or -1 if no such alarm exists. This is a
-         * blocking call and should not be done on the UI thread.
+         * blocking call and should not be done on the UI thread. TODO move to
+         * provider
          *
          * @param cr the ContentResolver
          * @param millis the time in UTC milliseconds
          * @return the next alarm time greater than or equal to "millis", or -1
          *         if no such alarm exists.
+         * @hide
          */
         public static final long findNextAlarmTime(ContentResolver cr, long millis) {
             String selection = ALARM_TIME + ">=" + millis;
             // TODO: construct an explicit SQL query so that we can add
             // "LIMIT 1" to the end and get just one result.
             String[] projection = new String[] { ALARM_TIME };
-            Cursor cursor = query(cr, projection,
-                    WHERE_FINDNEXTALARMTIME,
-                    new String[] {
+            Cursor cursor = cr.query(CONTENT_URI, projection, WHERE_FINDNEXTALARMTIME,
+                    (new String[] {
                         Long.toString(millis)
-                    },
-                    SORT_ORDER_ALARMTIME_ASC);
+                    }), SORT_ORDER_ALARMTIME_ASC);
             long alarmTime = -1;
             try {
                 if (cursor != null && cursor.moveToFirst()) {
@@ -2116,13 +2045,14 @@
 
         /**
          * Searches the CalendarAlerts table for alarms that should have fired
-         * but have not and then reschedules them.  This method can be called
-         * at boot time to restore alarms that may have been lost due to a
-         * phone reboot.
+         * but have not and then reschedules them. This method can be called at
+         * boot time to restore alarms that may have been lost due to a phone
+         * reboot. TODO move to provider
          *
          * @param cr the ContentResolver
          * @param context the Context
          * @param manager the AlarmManager
+         * @hide
          */
         public static final void rescheduleMissedAlarms(ContentResolver cr,
                 Context context, AlarmManager manager) {
@@ -2136,15 +2066,10 @@
 
             // TODO: construct an explicit SQL query so that we can add
             // "GROUPBY" instead of doing a sort and de-dup
-            Cursor cursor = CalendarAlerts.query(cr,
-                    projection,
-                    WHERE_RESCHEDULE_MISSED_ALARMS,
-                    new String[] {
-                        Long.toString(now),
-                        Long.toString(ancient),
-                        Long.toString(now)
-                    },
-                    SORT_ORDER_ALARMTIME_ASC);
+            Cursor cursor = cr.query(CalendarAlerts.CONTENT_URI, projection,
+                    WHERE_RESCHEDULE_MISSED_ALARMS, (new String[] {
+                            Long.toString(now), Long.toString(ancient), Long.toString(now)
+                    }), SORT_ORDER_ALARMTIME_ASC);
             if (cursor == null) {
                 return;
             }
@@ -2177,12 +2102,13 @@
          * keep scheduled reminders up to date but apps may use this to
          * implement snooze functionality without modifying the reminders table.
          * Scheduled alarms will generate an intent using
-         * {@link #ACTION_EVENT_REMINDER}.
+         * {@link #ACTION_EVENT_REMINDER}. TODO Move to provider
          *
          * @param context A context for referencing system resources
          * @param manager The AlarmManager to use or null
          * @param alarmTime The time to fire the intent in UTC millis since
          *            epoch
+         * @hide
          */
         public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
             if (DEBUG) {
@@ -2204,31 +2130,28 @@
         }
 
         /**
-         * Searches for an entry in the CalendarAlerts table that matches
-         * the given event id, begin time and alarm time.  If one is found
-         * then this alarm already exists and this method returns true.
-         *
+         * Searches for an entry in the CalendarAlerts table that matches the
+         * given event id, begin time and alarm time. If one is found then this
+         * alarm already exists and this method returns true. TODO Move to
+         * provider
+         * 
          * @param cr the ContentResolver
          * @param eventId the event id to match
          * @param begin the start time of the event in UTC millis
          * @param alarmTime the alarm time of the event in UTC millis
-         * @return true if there is already an alarm for the given event
-         *   with the same start time and alarm time.
+         * @return true if there is already an alarm for the given event with
+         *         the same start time and alarm time.
+         * @hide
          */
         public static final boolean alarmExists(ContentResolver cr, long eventId,
                 long begin, long alarmTime) {
             // TODO: construct an explicit SQL query so that we can add
             // "LIMIT 1" to the end and get just one result.
             String[] projection = new String[] { ALARM_TIME };
-            Cursor cursor = query(cr,
-                    projection,
-                    WHERE_ALARM_EXISTS,
-                    new String[] {
-                        Long.toString(eventId),
-                        Long.toString(begin),
-                        Long.toString(alarmTime)
-                    },
-                    null);
+            Cursor cursor = cr.query(CONTENT_URI, projection, WHERE_ALARM_EXISTS,
+                    (new String[] {
+                            Long.toString(eventId), Long.toString(begin), Long.toString(alarmTime)
+                    }), null);
             boolean found = false;
             try {
                 if (cursor != null && cursor.getCount() > 0) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 4107c5a..aae9ccf 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1,4 +1,4 @@
-/*
+ /*
  * Copyright (C) 2006 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -266,7 +266,7 @@
             }
         }
 
-        Alignment align = mAlignment;
+        Alignment paraAlign = mAlignment;
         TabStops tabStops = null;
         boolean tabStopsIsInitialized = false;
 
@@ -310,10 +310,10 @@
                                                     ParagraphStyle.class);
                     spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
 
-                    align = mAlignment;
+                    paraAlign = mAlignment;
                     for (int n = spans.length-1; n >= 0; n--) {
                         if (spans[n] instanceof AlignmentSpan) {
-                            align = ((AlignmentSpan) spans[n]).getAlignment();
+                            paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
                             break;
                         }
                     }
@@ -360,6 +360,16 @@
                 tabStopsIsInitialized = true;
             }
 
+            // Determine whether the line aligns to normal, opposite, or center.
+            Alignment align = paraAlign;
+            if (align == Alignment.ALIGN_LEFT) {
+                align = (dir == DIR_LEFT_TO_RIGHT) ?
+                    Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
+            } else if (align == Alignment.ALIGN_RIGHT) {
+                align = (dir == DIR_LEFT_TO_RIGHT) ?
+                    Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
+            }
+
             int x;
             if (align == Alignment.ALIGN_NORMAL) {
                 if (dir == DIR_LEFT_TO_RIGHT) {
@@ -411,7 +421,9 @@
         int dir = getParagraphDirection(line);
 
         int x;
-        if (align == Alignment.ALIGN_NORMAL) {
+        if (align == Alignment.ALIGN_LEFT) {
+            x = left;
+        } else if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_LEFT_TO_RIGHT) {
                 x = left;
             } else {
@@ -430,7 +442,9 @@
                 }
             }
             int max = (int)getLineExtent(line, tabStops, false);
-            if (align == Alignment.ALIGN_OPPOSITE) {
+            if (align == Alignment.ALIGN_RIGHT) {
+                x = right - max;
+            } else if (align == Alignment.ALIGN_OPPOSITE) {
                 if (dir == DIR_LEFT_TO_RIGHT) {
                     x = right - max;
                 } else {
@@ -738,11 +752,15 @@
         int dir = getParagraphDirection(line);
         Alignment align = getParagraphAlignment(line);
 
-        if (align == Alignment.ALIGN_NORMAL) {
+        if (align == Alignment.ALIGN_LEFT) {
+            return 0;
+        } else if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return getParagraphRight(line) - getLineMax(line);
             else
                 return 0;
+        } else if (align == Alignment.ALIGN_RIGHT) {
+            return mWidth - getLineMax(line);
         } else if (align == Alignment.ALIGN_OPPOSITE) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return 0;
@@ -765,11 +783,15 @@
         int dir = getParagraphDirection(line);
         Alignment align = getParagraphAlignment(line);
 
-        if (align == Alignment.ALIGN_NORMAL) {
+        if (align == Alignment.ALIGN_LEFT) {
+            return getParagraphLeft(line) + getLineMax(line);
+        } else if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return mWidth;
             else
                 return getParagraphLeft(line) + getLineMax(line);
+        } else if (align == Alignment.ALIGN_RIGHT) {
+            return mWidth;
         } else if (align == Alignment.ALIGN_OPPOSITE) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return getLineMax(line);
@@ -1765,8 +1787,10 @@
         ALIGN_NORMAL,
         ALIGN_OPPOSITE,
         ALIGN_CENTER,
-        // XXX ALIGN_LEFT,
-        // XXX ALIGN_RIGHT,
+        /** @hide */
+        ALIGN_LEFT,
+        /** @hide */
+        ALIGN_RIGHT,
     }
 
     private static final int TAB_INCREMENT = 20;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf7f359..bb5c954 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9121,9 +9121,15 @@
     }
 
     /**
-     * Reset the resolved layout direction by clearing the corresponding flag
+     * Reset the resolved layout direction.
+     *
+     * Subclasses need to override this method to clear cached information that depends on the
+     * resolved layout direction, or to inform child views that inherit their layout direction.
+     * Overrides must also call the superclass implementation at the start of their implementation.
+     *
+     * @hide
      */
-    void resetLayoutDirectionResolution() {
+    protected void resetLayoutDirectionResolution() {
         // Reset the current View resolution
         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2a90dde..da88fbb 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1746,6 +1746,7 @@
                 final long now = SystemClock.uptimeMillis();
                 event = MotionEvent.obtain(now, now,
                         MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                 syntheticEvent = true;
             }
 
@@ -4998,12 +4999,8 @@
         viewAncestor.requestTransitionStart(transition);
     }
 
-    /**
-     * This method will be called when we need to reset the layout direction resolution flag
-     *
-     */
     @Override
-    void resetLayoutDirectionResolution() {
+    protected void resetLayoutDirectionResolution() {
         super.resetLayoutDirectionResolution();
 
         // Take care of resetting the children resolution too
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 25f01a7..ac86769 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -25,40 +25,51 @@
 import java.util.List;
 
 /**
+ * <p>
  * 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>
  * <p>
  * An accessibility event is fired by an individual view which populates the event with
- * a record for its state and requests from its parent to send the event to interested
- * parties. The parent can optionally add a record for itself before dispatching a similar
- * request to its parent. A parent can also choose not to respect the request for sending
- * an event. The accessibility event is sent by the topmost view in the view tree.
- * Therefore, an {@link android.accessibilityservice.AccessibilityService} can explore
- * all records in an accessibility event to obtain more information about the context
- * in which the event was fired.
+ * data for its state and requests from its parent to send the event to interested
+ * parties. The parent can optionally add an {@link AccessibilityRecord} for itself before
+ * dispatching a similar request to its parent. A parent can also choose not to respect the
+ * request for sending an event. The accessibility event is sent by the topmost view in the
+ * view tree. Therefore, an {@link android.accessibilityservice.AccessibilityService} can
+ * explore all records in an accessibility event to obtain more information about the
+ * context in which the event was fired.
+ * </p>
  * <p>
- * A client can add, remove, and modify records. The getters and setters for individual
- * properties operate on the current record which can be explicitly set by the client. By
- * default current is the first record. Thus, querying a record would require setting
- * it as the current one and interacting with the property getters and setters.
+ * The main purpose of an accessibility event is to expose enough information for an
+ * {@link android.accessibilityservice.AccessibilityService} to provide meaningful feedback
+ * to the user. Sometimes however, an accessibility service may need more contextual
+ * information then the one in the event pay-load. In such cases the service can obtain
+ * the event source which is an {@link AccessibilityNodeInfo} (snapshot of a View state)
+ * which can be used for exploring the window content. Note that the privilege for accessing
+ * an event's source, thus the window content, has to be explicitly requested. For more
+ * details refer to {@link android.accessibilityservice.AccessibilityService}. If an
+ * accessibility service has not requested to retrieve the window content the event will
+ * not contain reference to its source. Also for events of type
+ * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available.
+ * </p>
  * <p>
  * This class represents various semantically different accessibility event
- * types. Each event type has associated a set of related properties. In other
+ * types. Each event type has an associated 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:
+ * in this class. Follows a specification of the event types and their associated properties:
+ * </p>
  * <p>
- * <b>VIEW TYPES</b> <br>
+ * <b>VIEW TYPES</b></br>
+ * </p>
  * <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:</br>
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br>
+ * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -67,13 +78,14 @@
  *   <li>{@link #isPassword()} - Whether the source is password.</li>
  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
  * </ul>
+ * </p>
  * <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:</br>
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br>
+ * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -82,13 +94,14 @@
  *   <li>{@link #isPassword()} - Whether the source is password.</li>
  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
  * </ul>
+ * </p>
  * <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:</br>
+ * the context of an {@link android.widget.AdapterView}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -96,17 +109,17 @@
  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
  *   <li>{@link #isPassword()} - Whether the source is password.</li>
  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
- *   <li>{@link #getItemCount()} -The number of selectable items of the source.</li>
+ *   <li>{@link #getItemCount()} - The number of selectable items of the source.</li>
  *   <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
  * </ul>
- * <p>
+ * </p>
  * <p>
  * <b>View focused</b> - represents the event of focusing a
- * {@link android.view.View}. <br>
- * Type: {@link #TYPE_VIEW_FOCUSED} <br>
- * Properties:</br>
+ * {@link android.view.View}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -114,16 +127,17 @@
  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
  *   <li>{@link #isPassword()} - Whether the source is password.</li>
  *   <li>{@link #isChecked()} - Whether the source is checked.</li>
- *   <li>{@link #getItemCount()} -The number of focusable items on the screen.</li>
+ *   <li>{@link #getItemCount()} - The number of focusable items on the screen.</li>
  *   <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
  * </ul>
+ * </p>
  * <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:</br>
+ * {@link android.widget.EditText}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -136,13 +150,14 @@
  *   <li>{@link #getRemovedCount()} - The number of removed characters.</li>
  *   <li>{@link #getBeforeText()} - The text of the source before the change.</li>
  * </ul>
+ * </p>
  * <p>
  * <b>View text selection changed</b> - represents the event of changing the text
- * selection of an {@link android.widget.EditText}.<br>
- * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} <br>
- * Properties:</br>
+ * selection of an {@link android.widget.EditText}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -152,7 +167,8 @@
  *   <li>{@link #getFromIndex()} - The selection start index.</li>
  *   <li>{@link #getToIndex()} - The selection end index.</li>
  *   <li>{@link #getItemCount()} - The length of the source text.</li>
- * <ul>
+ * </ul>
+ * </p>
  * <p>
  * <b>View scrolled</b> - represents the event of scrolling a view. If
  * the source is a descendant of {@link android.widget.AdapterView} the
@@ -161,11 +177,11 @@
  * is unaware if its pixel size since its adapter is responsible for
  * creating views. In all other cases the scroll is reported as the current
  * scroll on the X and Y axis respectively plus the height of the source in
- * pixels.<br>
- * Type: {@link #TYPE_VIEW_SCROLLED} <br>
- * Properties:</br>
+ * pixels.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
@@ -181,41 +197,49 @@
  *                               (for descendants of AdapterView).</li>
  *   <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView)
  *                                 or the height of the source in pixels (all other cases).</li>
- * <ul>
+ * </ul>
+ * </p>
  * <p>
- * <b>TRANSITION TYPES</b> <br>
- * <p>
+ * <b>TRANSITION TYPES</b></br>
+ * </p>
  * <b>Window state changed</b> - represents the event of opening a
  * {@link android.widget.PopupWindow}, {@link android.view.Menu},
- * {@link android.app.Dialog}, etc. <br>
- * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
- * Properties:</br>
+ * {@link android.app.Dialog}, etc.</br>
+ * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
  *   <li>{@link #getText()} - The text of the source.</li>
  * </ul>
+ * </p>
  * <p>
  * <b>Window content changed</b> - represents the event of change in the
  * content of a window. This change can be adding/removing view, changing
- * a view size, etc.<br>
- * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br>
- * Properties:</br>
+ * a view size, etc.</br>
+ * <p>
+ * <strong>Note:</strong> This event is fired only for the window source of the
+ * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED})
+ * and its purpose is to notify clients that the content of the user interaction
+ * window has changed.
+ * </p>
+ * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
+ * <em>Properties:</em></br>
  * <ul>
- *   <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
  *   <li>{@link #getEventTime()}  - The event time.</li>
- * <ul>
+ * </ul>
  * <p>
- * <b>NOTIFICATION TYPES</b> <br>
+ * <b>NOTIFICATION TYPES</b></br>
  * <p>
- * <b>Notification state changed</b> - represents the event showing/hiding
+ * <b>Notification state changed</b> - represents the event showing
  * {@link android.app.Notification}.
- * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br>
- * Properties:</br>
+ * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
+ * <em>Properties:</em></br>
  * <ul>
  *   <li>{@link #getClassName()} - The class name of the source.</li>
  *   <li>{@link #getPackageName()} - The package name of the source.</li>
@@ -223,15 +247,17 @@
  *   <li>{@link #getText()} - The text of the source.</li>
  *   <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
  * </ul>
+ * </p>
  * <p>
  * <b>Security note</b>
  * <p>
- * Since an event contains the text of its source privacy can be compromised by leaking of
+ * Since an event contains the text of its source privacy can be compromised by leaking
  * 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
+ * @see AccessibilityNodeInfo
  */
 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
     private static final boolean DEBUG = false;
@@ -285,13 +311,13 @@
     public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
 
     /**
-     * Represents the event of opening/closing a {@link android.widget.PopupWindow},
+     * Represents the event of opening 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}.
+     * Represents the event showing a {@link android.app.Notification}.
      */
     public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
 
@@ -340,6 +366,13 @@
      * @see #TYPE_VIEW_TEXT_CHANGED
      * @see #TYPE_WINDOW_STATE_CHANGED
      * @see #TYPE_NOTIFICATION_STATE_CHANGED
+     * @see #TYPE_VIEW_HOVER_ENTER
+     * @see #TYPE_VIEW_HOVER_EXIT
+     * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
+     * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
+     * @see #TYPE_WINDOW_CONTENT_CHANGED
+     * @see #TYPE_VIEW_SCROLLED
+     * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
      */
     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
 
@@ -432,10 +465,10 @@
     }
 
     /**
-     * Gets the records at a given index.
+     * Gets the record at a given index.
      *
      * @param index The index.
-     * @return The records at the specified index.
+     * @return The record at the specified index.
      */
     public AccessibilityRecord getRecord(int index) {
         return mRecords.get(index);
@@ -506,7 +539,7 @@
 
     /**
      * Returns a cached instance if such is available or a new one is
-     * instantiated with type property set.
+     * instantiated with its type property set.
      *
      * @param eventType The event type.
      * @return An instance.
@@ -519,7 +552,7 @@
 
     /**
      * Returns a cached instance if such is available or a new one is
-     * instantiated with type property set.
+     * initialized with from the given <code>event</code>.
      *
      * @param event The other event.
      * @return An instance.
@@ -559,9 +592,10 @@
     }
 
     /**
-     * Return an instance back to be reused.
+     * Recycles an instance back to be reused.
      * <p>
-     * <b>Note: You must not touch the object after calling this function.</b>
+     *   <b>Note: You must not touch the object after calling this function.</b>
+     * </p>
      *
      * @throws IllegalStateException If the event is already recycled.
      */
@@ -714,7 +748,7 @@
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
-        builder.append("; EventType: ").append(eventTypeToString(mEventType));
+        builder.append("EventType: ").append(eventTypeToString(mEventType));
         builder.append("; EventTime: ").append(mEventTime);
         builder.append("; PackageName: ").append(mPackageName);
         builder.append(super.toString());
@@ -758,11 +792,11 @@
      * Returns the string representation of an event type. For example,
      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
      *
-     * @param feedbackType The event type
+     * @param eventType The event type
      * @return The string representation.
      */
-    public static String eventTypeToString(int feedbackType) {
-        switch (feedbackType) {
+    public static String eventTypeToString(int eventType) {
+        switch (eventType) {
             case TYPE_VIEW_CLICKED:
                 return "TYPE_VIEW_CLICKED";
             case TYPE_VIEW_LONG_CLICKED:
diff --git a/core/java/android/view/accessibility/AccessibilityEventSource.java b/core/java/android/view/accessibility/AccessibilityEventSource.java
index 3d70959..f11880b 100644
--- a/core/java/android/view/accessibility/AccessibilityEventSource.java
+++ b/core/java/android/view/accessibility/AccessibilityEventSource.java
@@ -24,11 +24,12 @@
     /**
      * 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)}.
+     * via calling {@link AccessibilityManager#isEnabled() AccessibilityManager.isEnabled()},
+     * obtain an {@link AccessibilityEvent} from the event pool through calling
+     * {@link AccessibilityEvent#obtain(int) AccessibilityEvent.obtain(int)}, populate the
+     * event, and send it for dispatch via calling
+     * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)
+     * AccessibilityManager.sendAccessibilityEvent(AccessibilityEvent)}.
      *
      * @see AccessibilityEvent
      * @see AccessibilityManager
@@ -41,7 +42,8 @@
      * 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()}.
+     * to do the check via calling {@link AccessibilityManager#isEnabled()
+     * AccessibilityManager.isEnabled()}.
      *
      * @see AccessibilityEvent
      * @see AccessibilityManager
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index eece64a..314b7ca 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -37,16 +37,30 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
- * 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,
+ * System level service that serves as an event dispatch for {@link AccessibilityEvent}s,
+ * and provides facilities for querying the accessibility state of the system.
+ * Accessibility 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}.
+ * <p>
+ * To obtain a handle to the accessibility manager do the following:
+ * </p>
+ * <p>
+ * <code>
+ * <pre>
+ *   AccessibilityManager accessibilityManager =
+ *           (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ * </pre>
+ * </code>
+ * </p>
  *
  * @see AccessibilityEvent
+ * @see AccessibilityNodeInfo
  * @see android.accessibilityservice.AccessibilityService
- * @see android.content.Context#getSystemService
+ * @see Context#getSystemService
+ * @see Context#ACCESSIBILITY_SERVICE
  */
 public final class AccessibilityManager {
     private static final boolean DEBUG = false;
@@ -72,10 +86,11 @@
      * Listener for the accessibility state.
      */
     public interface AccessibilityStateChangeListener {
+
         /**
          * Called back on change in the accessibility state.
          *
-         * @param enabled
+         * @param enabled Whether accessibility is enabled.
          */
         public void onAccessibilityStateChanged(boolean enabled);
     }
@@ -142,9 +157,9 @@
     }
 
     /**
-     * Returns if the {@link AccessibilityManager} is enabled.
+     * Returns if the accessibility in the system is enabled.
      *
-     * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
+     * @return True if accessibility is enabled, false otherwise.
      */
     public boolean isEnabled() {
         synchronized (mHandler) {
@@ -161,17 +176,15 @@
      * @hide
      */
     public IAccessibilityManagerClient getClient() {
-       return (IAccessibilityManagerClient) mClient.asBinder(); 
+       return (IAccessibilityManagerClient) mClient.asBinder();
     }
 
     /**
-     * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not
-     * enabled the call is a NOOP.
+     * Sends an {@link AccessibilityEvent}.
      *
-     * @param event The {@link AccessibilityEvent}.
+     * @param event The event to send.
      *
-     * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent}
-     *         while accessibility is not enabled.
+     * @throws IllegalStateException if accessibility is not enabled.
      */
     public void sendAccessibilityEvent(AccessibilityEvent event) {
         if (!mIsEnabled) {
@@ -199,7 +212,7 @@
     }
 
     /**
-     * Requests interruption of the accessibility feedback from all accessibility services.
+     * Requests feedback interruption from all accessibility services.
      */
     public void interrupt() {
         if (!mIsEnabled) {
@@ -256,13 +269,20 @@
      * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
      * for a given feedback type.
      *
-     * @param feedbackType The feedback type (can be bitwise or of multiple types).
+     * @param feedbackTypeFlags The feedback type flags.
      * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
+     *
+     * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
+     * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
+     * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
+     * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
+     * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
      */
-    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
+            int feedbackTypeFlags) {
         List<AccessibilityServiceInfo> services = null;
         try {
-            services = mService.getEnabledAccessibilityServiceList(feedbackType);
+            services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags);
             if (DEBUG) {
                 Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
             }
@@ -273,7 +293,8 @@
     }
 
     /**
-     * Registers an {@link AccessibilityStateChangeListener}.
+     * Registers an {@link AccessibilityStateChangeListener} for changes in
+     * the global accessibility state of the system.
      *
      * @param listener The listener.
      * @return True if successfully registered.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index dbbe7be..031c6ae 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -22,7 +22,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.text.TextUtils;
-import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.View;
 
@@ -30,12 +29,26 @@
 import java.util.List;
 
 /**
- * This class represents a node of the screen content. From the point of
- * view of an accessibility service the screen content is presented as tree
- * of accessibility nodes.
+ * This class represents a node of the window content as well as actions that
+ * can be requested from its source. From the point of view of an
+ * {@link android.accessibilityservice.AccessibilityService} a window content is
+ * presented as tree of accessibility node info which may or may not map one-to-one
+ * to the view hierarchy. In other words, a custom view is free to report itself as
+ * a tree of accessibility node info.
+ * </p>
+ * <p>
+ * Once an accessibility node info is delivered to an accessibility service it is
+ * made immutable and calling a state mutation method generates an error.
+ * </p>
+ * <p>
+ * Please refer to {@link android.accessibilityservice.AccessibilityService} for
+ * details about how to obtain a handle to window content as a tree of accessibility
+ * node info as well as familiarizing with the security model.
+ * </p>
  *
- * TODO(svertoslavganov): Update the documentation, add sample, and describe
- *                        the security policy.
+ * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityEvent
+ * @see AccessibilityManager
  */
 public class AccessibilityNodeInfo implements Parcelable {
 
@@ -85,9 +98,6 @@
 
     private static final int PROPERTY_SCROLLABLE = 0x00000200;
 
-    // Readable representations - lazily initialized.
-    private static SparseArray<String> sActionSymbolicNames;
-
     // Housekeeping.
     private static final int MAX_POOL_SIZE = 50;
     private static final Object sPoolLock = new Object();
@@ -154,12 +164,11 @@
     /**
      * Get the child at given index.
      * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
      * </p>
+     *
      * @param index The child index.
      * @return The child node.
      *
@@ -184,9 +193,11 @@
     /**
      * Adds a child.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param child The child.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -215,9 +226,11 @@
     /**
      * Adds an action that can be performed on the node.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param action The action.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -230,9 +243,10 @@
     /**
      * Performs an action on the node.
      * <p>
-     *   Note: An action can be performed only if the request is made
+     *   <strong>Note:</strong> An action can be performed only if the request is made
      *   from an {@link android.accessibilityservice.AccessibilityService}.
      * </p>
+     *
      * @param action The action to perform.
      * @return True if the action was performed.
      *
@@ -256,6 +270,11 @@
      * Finds {@link AccessibilityNodeInfo}s by text. The match is case
      * insensitive containment. The search is relative to this info i.e.
      * this info is the root of the traversed tree.
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
      *
      * @param text The searched text.
      * @return A list of node info.
@@ -277,12 +296,11 @@
     /**
      * Gets the unique id identifying this node's parent.
      * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
      * </p>
+     *
      * @return The node's patent id.
      */
     public AccessibilityNodeInfo getParent() {
@@ -302,9 +320,11 @@
     /**
      * Sets the parent.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param parent The parent.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -327,9 +347,11 @@
     /**
      * Sets the node bounds in parent coordinates.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param bounds The node bounds.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -352,9 +374,11 @@
     /**
      * Sets the node bounds in screen coordinates.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param bounds The node bounds.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -376,9 +400,11 @@
     /**
      * Sets whether this node is checkable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param checkable True if the node is checkable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -399,9 +425,11 @@
     /**
      * Sets whether this node is checked.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param checked True if the node is checked.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -422,9 +450,11 @@
     /**
      * Sets whether this node is focusable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param focusable True if the node is focusable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -445,9 +475,11 @@
     /**
      * Sets whether this node is focused.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param focused True if the node is focused.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -468,9 +500,11 @@
     /**
      * Sets whether this node is selected.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param selected True if the node is selected.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -491,9 +525,11 @@
     /**
      * Sets whether this node is clickable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param clickable True if the node is clickable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -514,9 +550,11 @@
     /**
      * Sets whether this node is long clickable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param longClickable True if the node is long clickable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -537,9 +575,11 @@
     /**
      * Sets whether this node is enabled.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param enabled True if the node is enabled.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -560,9 +600,11 @@
     /**
      * Sets whether this node is a password.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param password True if the node is a password.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -582,6 +624,11 @@
 
     /**
      * Sets if the node is scrollable.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
      *
      * @param scrollable True if the node is scrollable, false otherwise.
      *
@@ -604,9 +651,11 @@
     /**
      * Sets the package this node comes from.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param packageName The package name.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -628,9 +677,11 @@
     /**
      * Sets the class this node comes from.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param className The class name.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -652,9 +703,11 @@
     /**
      * Sets the text of this node.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param text The text.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -676,9 +729,11 @@
     /**
      * Sets the content description of this node.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param contentDescription The content description.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -820,7 +875,7 @@
     /**
      * Return an instance back to be reused.
      * <p>
-     * <b>Note: You must not touch the object after calling this function.</b>
+     * <strong>Note:</strong> You must not touch the object after calling this function.
      *
      * @throws IllegalStateException If the info is already recycled.
      */
@@ -842,8 +897,8 @@
     /**
      * {@inheritDoc}
      * <p>
-     *   <b>Note: After the instance is written to a parcel it is recycled.
-     *      You must not touch the object after calling this function.</b>
+     *   <strong>Note:</strong> After the instance is written to a parcel it
+     *      is recycled. You must not touch the object after calling this function.
      * </p>
      */
     public void writeToParcel(Parcel parcel, int flags) {
@@ -885,7 +940,7 @@
         TextUtils.writeToParcel(mContentDescription, parcel, flags);
 
         // Since instances of this class are fetched via synchronous i.e. blocking
-        // calls in IPCs and we always recycle as soon as the instance is marshaled.
+        // calls in IPCs we always recycle as soon as the instance is marshaled.
         recycle();
     }
 
@@ -957,15 +1012,18 @@
      * @return The symbolic name.
      */
     private static String getActionSymbolicName(int action) {
-        SparseArray<String> actionSymbolicNames = sActionSymbolicNames;
-        if (actionSymbolicNames == null) {
-            actionSymbolicNames = sActionSymbolicNames = new SparseArray<String>();
-            actionSymbolicNames.put(ACTION_FOCUS, "ACTION_FOCUS");
-            actionSymbolicNames.put(ACTION_CLEAR_FOCUS, "ACTION_UNFOCUS");
-            actionSymbolicNames.put(ACTION_SELECT, "ACTION_SELECT");
-            actionSymbolicNames.put(ACTION_CLEAR_SELECTION, "ACTION_UNSELECT");
+        switch (action) {
+            case ACTION_FOCUS:
+                return "ACTION_FOCUS";
+            case ACTION_CLEAR_FOCUS:
+                return "ACTION_CLEAR_FOCUS";
+            case ACTION_SELECT:
+                return "ACTION_SELECT";
+            case ACTION_CLEAR_SELECTION:
+                return "ACTION_CLEAR_SELECTION";
+            default:
+                throw new IllegalArgumentException("Unknown action: " + action);
         }
-        return actionSymbolicNames.get(action);
     }
 
     private boolean canPerformRequestOverConnection(int accessibilityViewId) {
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index b9815c5..f4d5e89 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -25,12 +25,28 @@
 import java.util.List;
 
 /**
- * Represents a record in an accessibility event. This class encapsulates
- * the information for a {@link android.view.View}. Note that not all properties
- * are applicable to all view types. For detailed information please refer to
- * {@link AccessibilityEvent}.
+ * Represents a record in an {@link AccessibilityEvent} and contains information
+ * about state change of its source {@link android.view.View}. When a view fires
+ * an accessibility event it requests from its parent to dispatch the
+ * constructed event. The parent may optionally append a record for itself
+ * for providing more context to
+ * {@link android.accessibilityservice.AccessibilityService}s. Hence,
+ * accessibility services can facilitate additional accessibility records
+ * to enhance feedback.
+ * </p>
+ * <p>
+ * Once the accessibility event containing a record is dispatched the record is
+ * made immutable and calling a state mutation method generates an error.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Not all properties are applicable to all accessibility
+ * event types. For detailed information please refer to {@link AccessibilityEvent}.
+ * </p>
  *
  * @see AccessibilityEvent
+ * @see AccessibilityManager
+ * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityNodeInfo
  */
 public class AccessibilityRecord {
 
@@ -79,32 +95,6 @@
     }
 
     /**
-     * Initialize this record from another one.
-     *
-     * @param record The to initialize from.
-     */
-    void init(AccessibilityRecord record) {
-        mSealed = record.mSealed;
-        mBooleanProperties = record.mBooleanProperties;
-        mCurrentItemIndex = record.mCurrentItemIndex;
-        mItemCount = record.mItemCount;
-        mFromIndex = record.mFromIndex;
-        mToIndex = record.mToIndex;
-        mScrollX = record.mScrollX;
-        mScrollY = record.mScrollY;
-        mAddedCount = record.mAddedCount;
-        mRemovedCount = record.mRemovedCount;
-        mClassName = record.mClassName;
-        mContentDescription = record.mContentDescription;
-        mBeforeText = record.mBeforeText;
-        mParcelableData = record.mParcelableData;
-        mText.addAll(record.mText);
-        mSourceWindowId = record.mSourceWindowId;
-        mSourceViewId = record.mSourceViewId;
-        mConnection = record.mConnection;
-    }
-
-    /**
      * Sets the event source.
      *
      * @param source The source.
@@ -125,13 +115,12 @@
     /**
      * Gets the {@link AccessibilityNodeInfo} of the event source.
      * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the received info
+     *   by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
+     *   to avoid creating of multiple instances.
+     *
      * </p>
-     * @return The info.
+     * @return The info of the source.
      */
     public AccessibilityNodeInfo getSource() {
         enforceSealed();
@@ -641,7 +630,7 @@
     /**
      * Return an instance back to be reused.
      * <p>
-     * <b>Note: You must not touch the object after calling this function.</b>
+     * <strong>Note:</strong> You must not touch the object after calling this function.
      *
      * @throws IllegalStateException If the record is already recycled.
      */
@@ -661,6 +650,32 @@
     }
 
     /**
+     * Initialize this record from another one.
+     *
+     * @param record The to initialize from.
+     */
+    void init(AccessibilityRecord record) {
+        mSealed = record.mSealed;
+        mBooleanProperties = record.mBooleanProperties;
+        mCurrentItemIndex = record.mCurrentItemIndex;
+        mItemCount = record.mItemCount;
+        mFromIndex = record.mFromIndex;
+        mToIndex = record.mToIndex;
+        mScrollX = record.mScrollX;
+        mScrollY = record.mScrollY;
+        mAddedCount = record.mAddedCount;
+        mRemovedCount = record.mRemovedCount;
+        mClassName = record.mClassName;
+        mContentDescription = record.mContentDescription;
+        mBeforeText = record.mBeforeText;
+        mParcelableData = record.mParcelableData;
+        mText.addAll(record.mText);
+        mSourceWindowId = record.mSourceWindowId;
+        mSourceViewId = record.mSourceViewId;
+        mConnection = record.mConnection;
+    }
+
+    /**
      * Clears the state of this instance.
      */
     void clear() {
diff --git a/core/java/android/view/accessibility/package.html b/core/java/android/view/accessibility/package.html
new file mode 100644
index 0000000..4afafd3
--- /dev/null
+++ b/core/java/android/view/accessibility/package.html
@@ -0,0 +1,39 @@
+<html>
+<body>
+<p>
+  The classes in this package are used to represent screen content and changes to it
+  as well as APIs for querying the global accessibility state of the system.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityEvent}s 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>
+<p>
+  {@link android.view.accessibility.AccessibilityRecord} contains information
+  about state change of its source {@link android.view.View}. When a view fires
+  an accessibility event it requests from its parent to dispatch the
+  constructed event. The parent may optionally append a record for itself for
+  providing more context to {@link android.accessibilityservice.AccessibilityService}s.
+  Hence, accessibility services can facilitate additional accessibility records
+  to enhance feedback.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityNodeInfo} represents a node of the
+  window content as well as actions that can be requested from its source. From the point
+  of view of an {@link android.accessibilityservice.AccessibilityService} a window content is
+  presented as tree of accessibility node info which may or may not map one-to-one
+  to the view hierarchy. In other words, a custom view is free to report itself as
+  a tree of accessibility node info.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityManager} is a system level service that
+  serves as an event dispatch for  {@link android.view.accessibility.AccessibilityEvent}s,
+  and provides facilities for querying the accessibility state of the system. Accessibility
+  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}.
+</p>
+</body>
+</html>
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 7e41d36..4f97066 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1950,6 +1950,7 @@
     // mInitialViewState is set by didFirstLayout() and then reset in the
     // next webkitDraw after passing the state to the UI thread.
     private ViewState mInitialViewState = null;
+    private boolean mFirstLayoutForNonStandardLoad;
 
     static class ViewState {
         float mMinScale;
@@ -1977,6 +1978,7 @@
         int mMinPrefWidth;
         // only non-null if it is for the first picture set after the first layout
         ViewState mViewState;
+        boolean mFirstLayoutForNonStandardLoad;
         boolean mFocusSizeChanged;
     }
 
@@ -2026,6 +2028,10 @@
                 draw.mViewState = mInitialViewState;
                 mInitialViewState = null;
             }
+            if (mFirstLayoutForNonStandardLoad) {
+                draw.mFirstLayoutForNonStandardLoad = true;
+                mFirstLayoutForNonStandardLoad = false;
+            }
             if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
             Message.obtain(mWebView.mPrivateHandler,
                     WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
@@ -2312,6 +2318,8 @@
 
         // if mViewportWidth is 0, it means device-width, always update.
         if (mViewportWidth != 0 && !updateViewState) {
+            // For non standard load, since updateViewState will be false.
+            mFirstLayoutForNonStandardLoad = true;
             ViewState viewState = new ViewState();
             viewState.mMinScale = mViewportMinimumScale / 100.0f;
             viewState.mMaxScale = mViewportMaximumScale / 100.0f;
@@ -2471,9 +2479,10 @@
     // called by JNI
     private void restoreScale(float scale, float textWrapScale) {
         if (mBrowserFrame.firstLayoutDone() == false) {
-            mRestoredScale = scale;
+            final float defaultScale = mWebView.getDefaultZoomScale();
+            mRestoredScale = (scale <= 0.0) ? defaultScale : scale;
             if (mSettings.getUseWideViewPort()) {
-                mRestoredTextWrapScale = textWrapScale;
+                mRestoredTextWrapScale = (textWrapScale <= 0.0) ? defaultScale : textWrapScale;
             }
         }
     }
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 6c6974b..7d43e94 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -1024,6 +1024,11 @@
         } else {
             mInZoomOverview = !scaleHasDiff;
         }
+        if (drawData.mFirstLayoutForNonStandardLoad && settings.getLoadWithOverviewMode()) {
+            // Set mInitialZoomOverview in case this is the first picture for non standard load,
+            // so next new picture could be forced into overview mode if it's true.
+            mInitialZoomOverview = mInZoomOverview;
+        }
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2a70ac8..939779f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -340,6 +340,16 @@
 
     private WordIterator mWordIterator;
 
+    // The alignment to pass to Layout, or null if not resolved.
+    private Layout.Alignment mLayoutAlignment;
+
+    // The default value for mTextAlign.
+    private TextAlign mTextAlign = TextAlign.INHERIT;
+
+    private static enum TextAlign {
+        INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
+    }
+
     /*
      * Kick-start the font cache for the zygote process (to pay the cost of
      * initializing freetype for our default font only once).
@@ -5532,6 +5542,73 @@
                       physicalWidth, false);
     }
 
+    @Override
+    protected void resetLayoutDirectionResolution() {
+        super.resetLayoutDirectionResolution();
+
+        if (mLayoutAlignment != null &&
+                (mTextAlign == TextAlign.VIEW_START ||
+                mTextAlign == TextAlign.VIEW_END)) {
+            mLayoutAlignment = null;
+        }
+    }
+
+    private Layout.Alignment getLayoutAlignment() {
+        if (mLayoutAlignment == null) {
+            Layout.Alignment alignment;
+            TextAlign textAlign = mTextAlign;
+            switch (textAlign) {
+                case INHERIT:
+                    // fall through to gravity temporarily
+                    // intention is to inherit value through view hierarchy.
+                case GRAVITY:
+                    switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
+                        case Gravity.START:
+                            alignment = Layout.Alignment.ALIGN_NORMAL;
+                            break;
+                        case Gravity.END:
+                            alignment = Layout.Alignment.ALIGN_OPPOSITE;
+                            break;
+                        case Gravity.LEFT:
+                            alignment = Layout.Alignment.ALIGN_LEFT;
+                            break;
+                        case Gravity.RIGHT:
+                            alignment = Layout.Alignment.ALIGN_RIGHT;
+                            break;
+                        case Gravity.CENTER_HORIZONTAL:
+                            alignment = Layout.Alignment.ALIGN_CENTER;
+                            break;
+                        default:
+                            alignment = Layout.Alignment.ALIGN_NORMAL;
+                            break;
+                    }
+                    break;
+                case TEXT_START:
+                    alignment = Layout.Alignment.ALIGN_NORMAL;
+                    break;
+                case TEXT_END:
+                    alignment = Layout.Alignment.ALIGN_OPPOSITE;
+                    break;
+                case CENTER:
+                    alignment = Layout.Alignment.ALIGN_CENTER;
+                    break;
+                case VIEW_START:
+                    alignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                            Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_LEFT;
+                    break;
+                case VIEW_END:
+                    alignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                            Layout.Alignment.ALIGN_LEFT : Layout.Alignment.ALIGN_RIGHT;
+                    break;
+                default:
+                    alignment = Layout.Alignment.ALIGN_NORMAL;
+                    break;
+            }
+            mLayoutAlignment = alignment;
+        }
+        return mLayoutAlignment;
+    }
+
     /**
      * The width passed in is now the desired layout width,
      * not the full view width with padding.
@@ -5552,25 +5629,7 @@
             hintWidth = 0;
         }
 
-        final int layoutDirection = getResolvedLayoutDirection();
-        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
-        Layout.Alignment alignment;
-        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-            case Gravity.CENTER_HORIZONTAL:
-                alignment = Layout.Alignment.ALIGN_CENTER;
-                break;
-
-            case Gravity.RIGHT:
-                // Note, Layout resolves ALIGN_OPPOSITE to left or
-                // right based on the paragraph direction.
-                alignment = Layout.Alignment.ALIGN_OPPOSITE;
-                break;
-
-            default:
-                alignment = Layout.Alignment.ALIGN_NORMAL;
-        }
-
+        Layout.Alignment alignment = getLayoutAlignment();
         boolean shouldEllipsize = mEllipsize != null && mInput == null;
 
         if (mText instanceof Spannable) {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 8d5df6f..519acf5 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.app;
 
-import com.android.internal.R;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.SubMenuBuilder;
@@ -36,7 +35,6 @@
 import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.view.ActionMode;
@@ -580,6 +578,9 @@
 
         mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
         mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+        if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
+            mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
+        }
     }
 
     /**
@@ -620,6 +621,7 @@
 
             // Clear out the context mode views after the animation finishes
             mContextView.closeMode();
+
             mActionMode = null;
 
             if (mWasHiddenBeforeMode) {
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index d710cfa..953328c 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -105,24 +105,19 @@
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        int nonTabHeight = 0;
-        final int count = getChildCount();
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
+        if (mActionBarView == null) return;
 
-            if (child == mTabContainer) continue;
-
-            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            nonTabHeight = Math.max(nonTabHeight,
-                    child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
-        }
+        final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
+        final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
+                mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
 
         if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
             final int mode = MeasureSpec.getMode(heightMeasureSpec);
             if (mode == MeasureSpec.AT_MOST) {
                 final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
                 setMeasuredDimension(getMeasuredWidth(),
-                        Math.min(nonTabHeight + mTabContainer.getMeasuredHeight(), maxHeight));
+                        Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
+                                maxHeight));
             }
         }
     }
@@ -137,12 +132,14 @@
             if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
                 // Not showing home, put tabs on top.
                 final int count = getChildCount();
-                for (int i = 0; i < count; i++){
+                for (int i = 0; i < count; i++) {
                     final View child = getChildAt(i);
 
                     if (child == mTabContainer) continue;
 
-                    child.offsetTopAndBottom(tabHeight);
+                    if (!mActionBarView.isCollapsed()) {
+                        child.offsetTopAndBottom(tabHeight);
+                    }
                 }
                 mTabContainer.layout(l, 0, r, tabHeight);
             } else {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index fc43994..3e3eeab 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -287,7 +287,7 @@
             availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0);
         }
 
-        if (mMenuView != null) {
+        if (mMenuView != null && mMenuView.getParent() == this) {
             availableWidth = measureChildView(mMenuView, availableWidth,
                     childSpecHeight, 0);
         }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 8eb046e..09bc1fc 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -117,6 +117,7 @@
     private boolean mUserTitle;
     private boolean mIncludeTabs;
     private boolean mIsCollapsable;
+    private boolean mIsCollapsed;
 
     private MenuBuilder mOptionsMenu;
     
@@ -692,6 +693,10 @@
         mIsCollapsable = collapsable;
     }
 
+    public boolean isCollapsed() {
+        return mIsCollapsed;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int childCount = getChildCount();
@@ -708,9 +713,11 @@
             if (visibleChildren == 0) {
                 // No size for an empty action bar when collapsable.
                 setMeasuredDimension(0, 0);
+                mIsCollapsed = true;
                 return;
             }
         }
+        mIsCollapsed = false;
 
         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         if (widthMode != MeasureSpec.EXACTLY) {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 5b4d7ab..2f7adf0 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -15,6 +15,9 @@
  */
 package com.android.internal.widget;
 
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
 import android.app.ActionBar;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -22,6 +25,7 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -35,6 +39,13 @@
 
     int mMaxTabWidth;
 
+    protected Animator mVisibilityAnim;
+    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
+
+    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
+
+    private static final int FADE_DURATION = 200;
+
     public ScrollingTabContainerView(Context context) {
         super(context);
         setHorizontalScrollBarEnabled(false);
@@ -76,6 +87,30 @@
         }
     }
 
+    public void animateToVisibility(int visibility) {
+        if (mVisibilityAnim != null) {
+            mVisibilityAnim.cancel();
+        }
+        if (visibility == VISIBLE) {
+            if (getVisibility() != VISIBLE) {
+                setAlpha(0);
+            }
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
+            anim.setDuration(FADE_DURATION);
+            anim.setInterpolator(sAlphaInterpolator);
+
+            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+            anim.start();
+        } else {
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
+            anim.setDuration(FADE_DURATION);
+            anim.setInterpolator(sAlphaInterpolator);
+
+            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+            anim.start();
+        }
+    }
+
     public void animateToTab(int position) {
         final View tabView = mTabLayout.getChildAt(position);
         if (mTabSelector != null) {
@@ -259,4 +294,38 @@
             }
         }
     }
+
+    protected class VisibilityAnimListener implements Animator.AnimatorListener {
+        private boolean mCanceled = false;
+        private int mFinalVisibility;
+
+        public VisibilityAnimListener withFinalVisibility(int visibility) {
+            mFinalVisibility = visibility;
+            return this;
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            setVisibility(VISIBLE);
+            mVisibilityAnim = animation;
+            mCanceled = false;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mCanceled) return;
+
+            mVisibilityAnim = null;
+            setVisibility(mFinalVisibility);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCanceled = true;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 5b35104..04bb689 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -20,7 +20,7 @@
 
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
-import android.animation.ObjectAnimator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -43,9 +43,9 @@
  * A special widget containing a center and outer ring. Moving the center ring to the outer ring
  * causes an event that can be caught by implementing OnTriggerListener.
  */
-public class MultiWaveView extends View implements AnimatorUpdateListener {
+public class MultiWaveView extends View {
     private static final String TAG = "MultiWaveView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     // Wave state machine
     private static final int STATE_IDLE = 0;
@@ -67,14 +67,15 @@
     }
 
     // Tune-able parameters
-    private static final int CHEVRON_INCREMENTAL_DELAY = 50;
-    private static final int CHEVRON_ANIMATION_DURATION = 1000;
-    private static final int RETURN_TO_HOME_DURATION = 150;
-    private static final int HIDE_ANIMATION_DELAY = 500;
-    private static final int HIDE_ANIMATION_DURACTION = 2000;
+    private static final int CHEVRON_INCREMENTAL_DELAY = 160;
+    private static final int CHEVRON_ANIMATION_DURATION = 650;
+    private static final int RETURN_TO_HOME_DELAY = 1200;
+    private static final int RETURN_TO_HOME_DURATION = 300;
+    private static final int HIDE_ANIMATION_DELAY = 200;
+    private static final int HIDE_ANIMATION_DURATION = RETURN_TO_HOME_DELAY;
     private static final int SHOW_ANIMATION_DURATION = 0;
     private static final int SHOW_ANIMATION_DELAY = 0;
-    private TimeInterpolator mChevronAnimationInterpolator = Ease.Quint.easeOut;
+    private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
 
     private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
     private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
@@ -99,14 +100,31 @@
     private float mHitRadius = 0.0f;
     private float mSnapMargin = 0.0f;
     private boolean mDragging;
+    private int mNewTargetResources;
 
-    private AnimatorListener mResetListener = new Animator.AnimatorListener() {
-        public void onAnimationStart(Animator animation) { }
-        public void onAnimationRepeat(Animator animation) { }
-        public void onAnimationEnd(Animator animation) {
+    private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
             switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
         }
-        public void onAnimationCancel(Animator animation) { }
+    };
+
+    private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
+        public void onAnimationUpdate(ValueAnimator animation) {
+            invalidateGlobalRegion(mHandleDrawable);
+            invalidate();
+        }
+    };
+
+    private boolean mAnimatingTargets;
+    private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
+            if (mNewTargetResources != 0) {
+                internalSetTargetResources(mNewTargetResources);
+                mNewTargetResources = 0;
+                hideTargets(false);
+            }
+            mAnimatingTargets = false;
+        }
     };
 
     public MultiWaveView(Context context) {
@@ -135,31 +153,23 @@
         mOuterRing = new TargetDrawable(res, a.getDrawable(R.styleable.MultiWaveView_waveDrawable));
 
         // Read chevron animation drawables
-        Drawable leftChevron = a.getDrawable(R.styleable.MultiWaveView_leftChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    leftChevron != null ? new TargetDrawable(res, leftChevron) : null);
-        }
-        Drawable rightChevron = a.getDrawable(R.styleable.MultiWaveView_rightChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    rightChevron != null ? new TargetDrawable(res, rightChevron) : null);
-        }
-        Drawable topChevron = a.getDrawable(R.styleable.MultiWaveView_topChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    topChevron != null ? new TargetDrawable(res, topChevron) : null);
-        }
-        Drawable bottomChevron = a.getDrawable(R.styleable.MultiWaveView_bottomChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    bottomChevron != null ? new TargetDrawable(res, bottomChevron) : null);
+        final int chevrons[] = { R.styleable.MultiWaveView_leftChevronDrawable,
+                R.styleable.MultiWaveView_rightChevronDrawable,
+                R.styleable.MultiWaveView_topChevronDrawable,
+                R.styleable.MultiWaveView_bottomChevronDrawable
+        };
+        for (int chevron : chevrons) {
+            Drawable chevronDrawable = a.getDrawable(chevron);
+            for (int i = 0; i < mFeedbackCount; i++) {
+                mChevronDrawables.add(
+                    chevronDrawable != null ? new TargetDrawable(res, chevronDrawable) : null);
+            }
         }
 
         // Read array of target drawables
         TypedValue outValue = new TypedValue();
         if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
-            setTargetResources(outValue.resourceId);
+            internalSetTargetResources(outValue.resourceId);
         }
         if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
             throw new IllegalStateException("Must specify at least one target drawable");
@@ -205,7 +215,7 @@
             case STATE_FIRST_TOUCH:
                 stopHandleAnimation();
                 deactivateTargets();
-                showTargets();
+                showTargets(true);
                 mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
                 setGrabbedState(OnTriggerListener.CENTER_HANDLE);
                 break;
@@ -228,17 +238,18 @@
      * mFeedbackCount items in the order: left, right, top, bottom.
      */
     private void startChevronAnimation() {
-        final float r = mHandleDrawable.getWidth() / 2;
+        final float r = mHandleDrawable.getWidth() * 0.4f;
+        final float chevronAnimationDistance = mOuterRadius * 0.8f;
         final float from[][] = {
                 {mWaveCenterX - r, mWaveCenterY},  // left
                 {mWaveCenterX + r, mWaveCenterY},  // right
                 {mWaveCenterX, mWaveCenterY - r},  // top
                 {mWaveCenterX, mWaveCenterY + r} }; // bottom
         final float to[][] = {
-                {mWaveCenterX - mOuterRadius, mWaveCenterY},  // left
-                {mWaveCenterX + mOuterRadius, mWaveCenterY},  // right
-                {mWaveCenterX, mWaveCenterY - mOuterRadius},  // top
-                {mWaveCenterX, mWaveCenterY + mOuterRadius} }; // bottom
+                {mWaveCenterX - chevronAnimationDistance, mWaveCenterY},  // left
+                {mWaveCenterX + chevronAnimationDistance, mWaveCenterY},  // right
+                {mWaveCenterX, mWaveCenterY - chevronAnimationDistance},  // top
+                {mWaveCenterX, mWaveCenterY + chevronAnimationDistance} }; // bottom
 
         mChevronAnimations.clear();
         for (int direction = 0; direction < 4; direction++) {
@@ -254,7 +265,7 @@
                         "x", new float[] { from[direction][0], to[direction][0] },
                         "y", new float[] { from[direction][1], to[direction][1] },
                         "alpha", new float[] {1.0f, 0.0f},
-                        "onUpdate", this));
+                        "onUpdate", mUpdateListener));
             }
         }
     }
@@ -308,70 +319,109 @@
     }
 
     private void doFinish() {
-        // Inform listener of any active targets.  Typically only one will be active.
         final int activeTarget = mActiveTarget;
         boolean targetHit =  activeTarget != -1;
-        if (targetHit) {
-            Log.v(TAG, "Finish with target hit = " + targetHit);
-            dispatchTriggerEvent(mActiveTarget);
-        }
-
-        setGrabbedState(OnTriggerListener.NO_HANDLE);
-
-        // Animate finger outline back to home position
-        mHandleDrawable.setAlpha(targetHit ? 0.0f : 1.0f);
-        mHandleAnimation = Tweener.to(mHandleDrawable, RETURN_TO_HOME_DURATION,
-                "ease", Ease.Quart.easeOut,
-                "delay", targetHit ? HIDE_ANIMATION_DELAY : 0,
-                "alpha", 1.0f,
-                "x", mWaveCenterX,
-                "y", mWaveCenterY,
-                "onUpdate", this,
-                "onComplete", mResetListener);
 
         // Hide unselected targets
         hideTargets(true);
 
         // Highlight the selected one
+        mHandleDrawable.setAlpha(targetHit ? 0.0f : 1.0f);
         if (targetHit) {
             mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
+
+            hideUnselected(activeTarget);
+
+            // Inform listener of any active targets.  Typically only one will be active.
+            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+            dispatchTriggerEvent(mActiveTarget);
+            mHandleAnimation = Tweener.to(mHandleDrawable, 0,
+                    "ease", Ease.Quart.easeOut,
+                    "delay", RETURN_TO_HOME_DELAY,
+                    "alpha", 1.0f,
+                    "x", mWaveCenterX,
+                    "y", mWaveCenterY,
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mResetListener);
+        } else {
+            // Animate finger outline back to home position
+            mHandleAnimation = Tweener.to(mHandleDrawable, RETURN_TO_HOME_DURATION,
+                    "ease", Ease.Quart.easeOut,
+                    "delay", 0,
+                    "alpha", 1.0f,
+                    "x", mWaveCenterX,
+                    "y", mWaveCenterY,
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mResetListener);
         }
+
+        setGrabbedState(OnTriggerListener.NO_HANDLE);
+    }
+
+    private void hideUnselected(int active) {
+        for (int i = 0; i < mTargetDrawables.size(); i++) {
+            if (i != active) {
+                mTargetDrawables.get(i).setAlpha(0.0f);
+            }
+        }
+        mOuterRing.setAlpha(0.0f);
     }
 
     private void hideTargets(boolean animate) {
         if (mTargetAnimations.size() > 0) {
             stopTargetAnimation();
         }
-        for (TargetDrawable target : mTargetDrawables) {
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target,
-                    animate ? HIDE_ANIMATION_DURACTION : 0,
+        // Note: these animations should complete at the same time so that we can swap out
+        // the target assets asynchronously from the setTargetResources() call.
+        mAnimatingTargets = animate;
+        if (animate) {
+            final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                mTargetAnimations.add(Tweener.to(target, duration,
+                        "alpha", 0.0f,
+                        "delay", HIDE_ANIMATION_DELAY,
+                        "onUpdate", mUpdateListener));
+            }
+            mTargetAnimations.add(Tweener.to(mOuterRing, duration,
                     "alpha", 0.0f,
                     "delay", HIDE_ANIMATION_DELAY,
-                    "onUpdate", this));
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mTargetUpdateListener));
+        } else {
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                target.setAlpha(0.0f);
+            }
+            mOuterRing.setAlpha(0.0f);
         }
-        mTargetAnimations.add(Tweener.to(mOuterRing,
-                animate ? HIDE_ANIMATION_DURACTION : 0,
-                "alpha", 0.0f,
-                "delay", HIDE_ANIMATION_DELAY,
-                "onUpdate", this));
     }
 
-    private void showTargets() {
+    private void showTargets(boolean animate) {
         if (mTargetAnimations.size() > 0) {
             stopTargetAnimation();
         }
-        for (TargetDrawable target : mTargetDrawables) {
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target, SHOW_ANIMATION_DURATION,
+        mAnimatingTargets = animate;
+        if (animate) {
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                mTargetAnimations.add(Tweener.to(target, SHOW_ANIMATION_DURATION,
+                        "alpha", 1.0f,
+                        "delay", SHOW_ANIMATION_DELAY,
+                        "onUpdate", mUpdateListener));
+            }
+            mTargetAnimations.add(Tweener.to(mOuterRing, SHOW_ANIMATION_DURATION,
                     "alpha", 1.0f,
                     "delay", SHOW_ANIMATION_DELAY,
-                    "onUpdate", this));
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mTargetUpdateListener));
+        } else {
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                target.setAlpha(1.0f);
+            }
+            mOuterRing.setAlpha(1.0f);
         }
-        mTargetAnimations.add(Tweener.to(mOuterRing, SHOW_ANIMATION_DURATION,
-                "alpha", 1.0f,
-                "delay", SHOW_ANIMATION_DELAY,
-                "onUpdate", this));
     }
 
     private void stopTargetAnimation() {
@@ -387,12 +437,7 @@
         }
     }
 
-    /**
-     * Loads an array of drawables from the given resourceId.
-     *
-     * @param resourceId
-     */
-    public void setTargetResources(int resourceId) {
+    private void internalSetTargetResources(int resourceId) {
         Resources res = getContext().getResources();
         TypedArray array = res.obtainTypedArray(resourceId);
         int count = array.length();
@@ -402,6 +447,21 @@
             targetDrawables.add(new TargetDrawable(res, drawable));
         }
         mTargetDrawables = targetDrawables;
+        updateTargetPositions();
+    }
+
+    /**
+     * Loads an array of drawables from the given resourceId.
+     *
+     * @param resourceId
+     */
+    public void setTargetResources(int resourceId) {
+        if (mAnimatingTargets) {
+            // postpone this change until we return to the initial state
+            mNewTargetResources = resourceId;
+        } else {
+            internalSetTargetResources(resourceId);
+        }
     }
 
     /**
@@ -590,20 +650,9 @@
         }
     }
 
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        final int width = right - left;
-        final int height = bottom - top;
-
-        mWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
-        mWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
-        moveHandleTo(mWaveCenterX, mWaveCenterY, false);
-        mOuterRing.setX(mWaveCenterX);
-        mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
-        mOuterRing.setAlpha(0.0f);
+    private void performInitialLayout(float centerX, float centerY) {
         if (mOuterRadius == 0.0f) {
-            mOuterRadius = 0.5f*(float) Math.sqrt(dist2(mWaveCenterX, mWaveCenterY));
+            mOuterRadius = 0.5f*(float) Math.sqrt(dist2(centerX, centerY));
         }
         if (mHitRadius == 0.0f) {
             // Use the radius of inscribed circle of the first target.
@@ -613,6 +662,35 @@
             mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                     SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
         }
+        hideChevrons();
+        hideTargets(false);
+        moveHandleTo(centerX, centerY, false);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        final int width = right - left;
+        final int height = bottom - top;
+        float newWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
+        float newWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
+        if (newWaveCenterX != mWaveCenterX || newWaveCenterY != mWaveCenterY) {
+            if (mWaveCenterX == 0 && mWaveCenterY == 0) {
+                performInitialLayout(newWaveCenterX, newWaveCenterY);
+            }
+            mWaveCenterX = newWaveCenterX;
+            mWaveCenterY = newWaveCenterY;
+
+            mOuterRing.setX(mWaveCenterX);
+            mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
+
+            updateTargetPositions();
+        }
+        if (DEBUG) dump();
+    }
+
+    private void updateTargetPositions() {
+        // Reposition the target drawables if the view changed.
         for (int i = 0; i < mTargetDrawables.size(); i++) {
             final TargetDrawable targetIcon = mTargetDrawables.get(i);
             double angle = -2.0f * Math.PI * i / mTargetDrawables.size();
@@ -620,11 +698,7 @@
             float yPosition = mWaveCenterY + mOuterRadius * (float) Math.sin(angle);
             targetIcon.setX(xPosition);
             targetIcon.setY(yPosition);
-            targetIcon.setAlpha(0.0f);
         }
-        hideChevrons();
-        hideTargets(false);
-        if (DEBUG) dump();
     }
 
     private void hideChevrons() {
@@ -655,11 +729,6 @@
         mOnTriggerListener = listener;
     }
 
-    public void onAnimationUpdate(ValueAnimator animation) {
-        invalidateGlobalRegion(mHandleDrawable);
-        invalidate();
-    }
-
     private float square(float d) {
         return d * d;
     }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index fd61cfd..db33d1c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2208,7 +2208,8 @@
         <!-- The event types this serivce would like to receive as specified in
              {@link android.view.accessibility.AccessibilityEvent}. This setting
              can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityEventTypes">
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} events.-->
             <flag name="typeViewClicked" value="0x00000001" />
@@ -2232,17 +2233,24 @@
             <flag name="typeTouchExplorationGestureStart" value="0x00000200" />
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} events. -->
             <flag name="typeTouchExplorationGestureEnd" value="0x00000400" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events. -->
+            <flag name="typeWindowContentChanged" value="0x00000800" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED} events. -->
+            <flag name="typeViewScrolled" value="0x000001000" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} events. -->
+            <flag name="typeViewTextSelectionChanged" value="0x000002000" />
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
             <flag name="typeAllMask" value="0xffffffff" />
         </attr>
         <!-- Comma separated package names from which this serivce would like to receive events (leave out for all packages).
-             This setting can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="packageNames" format="string" />
         <!-- The feedback types this serivce provides as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting
              can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityFeedbackType">
             <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_SPOKEN} feedback. -->
             <flag name="feedbackSpoken" value="0x00000001" />
@@ -2255,14 +2263,16 @@
             <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
             <flag name="feedbackGeneric" value="0x00000010" />
         </attr>
-        <!-- The minimal period in milliseconds between two accessibility events are sent
-             to this serivce. This setting can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+        <!-- The minimal period in milliseconds between two accessibility events of the same type
+             are sent to this serivce. This setting can be changed at runtime by calling
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->>
         <attr name="notificationTimeout" format="integer" />
         <!-- Additional flags as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}.
              This setting can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityFlags">
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} -->
             <flag name="flagDefault" value="0x00000001" />
@@ -2271,7 +2281,7 @@
              the settings for this service. This setting cannot be changed at runtime. -->
         <attr name="settingsActivity" />
         <!-- Flag whether the accessibility service wants to be able to retrieve the
-             focused window content. This setting cannot be changed at runtime. -->
+             active window content. This setting cannot be changed at runtime. -->
         <attr name="canRetrieveWindowContent" format="boolean" />
     </declare-styleable>
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 513eda8..167071a 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2282,6 +2282,11 @@
             if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
                 CHECK(!mFlushComplete[data2]);
                 mFlushComplete[data2] = true;
+
+                if (mFlushComplete[kPortIndexInput]
+                        && mFlushComplete[kPortIndexOutput]) {
+                    changeStateIfWeOwnAllBuffers();
+                }
             } else {
                 CHECK_EQ(data2, OMX_ALL);
                 CHECK(mFlushComplete[kPortIndexInput]);
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 165683e..f1a2a60 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -408,13 +408,20 @@
         if (firstTime) {
             Mutex::Autolock autoLock(mLock);
 
-            int32_t targetDuration;
-            if (!mPlaylist->isComplete()
-                    || !mPlaylist->meta()->findInt32(
-                    "target-duration", &targetDuration)) {
+            if (!mPlaylist->isComplete()) {
                 mDurationUs = -1;
             } else {
-                mDurationUs = 1000000ll * targetDuration * mPlaylist->size();
+                mDurationUs = 0;
+                for (size_t i = 0; i < mPlaylist->size(); ++i) {
+                    sp<AMessage> itemMeta;
+                    CHECK(mPlaylist->itemAt(
+                                i, NULL /* uri */, &itemMeta));
+
+                    int64_t itemDurationUs;
+                    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+                    mDurationUs += itemDurationUs;
+                }
             }
         }
 
@@ -431,14 +438,26 @@
     bool bandwidthChanged = false;
 
     if (mSeekTimeUs >= 0) {
-        int32_t targetDuration;
-        if (mPlaylist->isComplete() &&
-                mPlaylist->meta()->findInt32(
-                    "target-duration", &targetDuration)) {
-            int64_t seekTimeSecs = (mSeekTimeUs + 500000ll) / 1000000ll;
-            int64_t index = seekTimeSecs / targetDuration;
+        if (mPlaylist->isComplete()) {
+            size_t index = 0;
+            int64_t segmentStartUs = 0;
+            while (index < mPlaylist->size()) {
+                sp<AMessage> itemMeta;
+                CHECK(mPlaylist->itemAt(
+                            index, NULL /* uri */, &itemMeta));
 
-            if (index >= 0 && index < mPlaylist->size()) {
+                int64_t itemDurationUs;
+                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+                if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
+                    break;
+                }
+
+                segmentStartUs += itemDurationUs;
+                ++index;
+            }
+
+            if (index < mPlaylist->size()) {
                 int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
 
                 if (newSeqNumber != mSeqNumber) {
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 765f795..123fbf8 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -64,14 +64,21 @@
 }
 
 bool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) {
-    uri->clear();
-    if (meta) { *meta = NULL; }
+    if (uri) {
+        uri->clear();
+    }
+
+    if (meta) {
+        *meta = NULL;
+    }
 
     if (index >= mItems.size()) {
         return false;
     }
 
-    *uri = mItems.itemAt(index).mURI;
+    if (uri) {
+        *uri = mItems.itemAt(index).mURI;
+    }
 
     if (meta) {
         *meta = mItems.itemAt(index).mMeta;
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index fd0505e..f03f7a2 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -301,9 +301,6 @@
 // static
 bool ASessionDescription::parseNTPRange(
         const char *s, float *npt1, float *npt2) {
-    *npt1 = 0.0f;
-    *npt2 = 0.0f;
-
     if (s[0] == '-') {
         return false;  // no start time available.
     }
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index f89f8e2..d15d9c5 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -995,12 +995,10 @@
         AString val;
         CHECK(GetAttribute(range.c_str(), "npt", &val));
 
-        bool seekable = true;
-
         float npt1, npt2;
         if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
             // This is a live stream and therefore not seekable.
-            seekable = false;
+            return;
         }
 
         i = response->mHeaders.indexOfKey("rtp-info");
@@ -1046,7 +1044,7 @@
             ++n;
         }
 
-        mSeekable = seekable;
+        mSeekable = true;
     }
 
     sp<APacketSource> getPacketSource(size_t index) {
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 8b7a61e..1c4084c 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -64,7 +64,6 @@
     private KeyguardUpdateMonitor mUpdateMonitor;
     private KeyguardScreenCallback mCallback;
 
-    private SlidingTab mSlidingTab;
     private TextView mScreenLocked;
     private TextView mEmergencyCallText;
     private Button mEmergencyCallButton;
@@ -89,11 +88,9 @@
     private boolean mEnableMenuKeyInLockScreen;
 
     private StatusView mStatusView;
-    private WaveView mEnergyWave;
-    private SlidingTabMethods mSlidingTabMethods;
-    private WaveViewMethods mWaveViewMethods;
-    private MultiWaveView mMultiWaveView;
-    private MultiWaveViewMethods mMultiWaveViewMethods;
+    private UnlockWidgetCommonMethods mUnlockWidgetMethods;
+    private View mUnlockWidget;
+
 
     /**
      * The status of this lock screen.
@@ -151,9 +148,28 @@
         }
     }
 
-    class SlidingTabMethods implements SlidingTab.OnTriggerListener {
+    private interface UnlockWidgetCommonMethods {
+        // Update resources based on phone state
+        public void updateResources();
 
-        private void updateRightTabResources() {
+        // Get the view associated with this widget
+        public View getView();
+
+        // Reset the view
+        public void reset(boolean animate);
+
+        // Animate the widget if it supports ping()
+        public void ping();
+    }
+
+    class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
+        private final SlidingTab mSlidingTab;
+
+        SlidingTabMethods(SlidingTab slidingTab) {
+            mSlidingTab = slidingTab;
+        }
+
+        public void updateResources() {
             boolean vibe = mSilentMode
                 && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
 
@@ -175,7 +191,6 @@
                 mCallback.goToUnlockScreen();
             } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
                 toggleRingMode();
-                updateRightTabResources();
                 doSilenceRingToast();
                 mCallback.pokeWakelock();
             }
@@ -195,12 +210,29 @@
                 mCallback.pokeWakelock();
             }
         }
+
+        public View getView() {
+            return mSlidingTab;
+        }
+
+        public void reset(boolean animate) {
+            mSlidingTab.reset(animate);
+        }
+
+        public void ping() {
+        }
     }
 
     private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
     private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
 
-    class WaveViewMethods implements WaveView.OnTriggerListener {
+    class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
+
+        private final WaveView mWaveView;
+
+        WaveViewMethods(WaveView waveView) {
+            mWaveView = waveView;
+        }
         /** {@inheritDoc} */
         public void onTrigger(View v, int whichHandle) {
             if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
@@ -210,8 +242,6 @@
 
         /** {@inheritDoc} */
         public void onGrabbedStateChange(View v, int grabbedState) {
-            if (DBG) Log.v(TAG, "*** LockScreen accel is "
-                    + (mEnergyWave.isHardwareAccelerated() ? "on":"off"));
             // Don't poke the wake lock when returning to a state where the handle is
             // not grabbed since that can happen when the system (instead of the user)
             // cancels the grab.
@@ -219,30 +249,51 @@
                 mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
             }
         }
+
+        public void updateResources() {
+        }
+
+        public View getView() {
+            return mWaveView;
+        }
+        public void reset(boolean animate) {
+            mWaveView.reset();
+        }
+        public void ping() {
+        }
     }
 
-    class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener {
+    class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
+            UnlockWidgetCommonMethods {
+
+        private final MultiWaveView mMultiWaveView;
+
+        MultiWaveViewMethods(MultiWaveView multiWaveView) {
+            mMultiWaveView = multiWaveView;
+        }
+
+        public void updateResources() {
+            mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
+                    : R.array.lockscreen_targets_when_soundon);
+        }
+
         public void onGrabbed(View v, int handle) {
 
         }
+
         public void onReleased(View v, int handle) {
 
         }
+
         public void onTrigger(View v, int target) {
             if (target == 0) { // TODO: Use resources to determine which handle was used
                 mCallback.goToUnlockScreen();
             } else if (target == 2) {
                 toggleRingMode();
-                updateResources();
                 doSilenceRingToast();
+                mUnlockWidgetMethods.updateResources();
                 mCallback.pokeWakelock();
             }
-
-        }
-
-        private void updateResources() {
-            mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
-                    : R.array.lockscreen_targets_when_soundon);
         }
 
         public void onGrabbedStateChange(View v, int handle) {
@@ -253,6 +304,18 @@
                 mCallback.pokeWakelock();
             }
         }
+
+        public View getView() {
+            return mMultiWaveView;
+        }
+
+        public void reset(boolean animate) {
+            mMultiWaveView.reset(animate);
+        }
+
+        public void ping() {
+            mMultiWaveView.ping();
+        }
     }
 
     private void requestUnlockScreen() {
@@ -371,32 +434,39 @@
         mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
         mSilentMode = isSilentMode();
 
-        View unlockWidget = findViewById(R.id.unlock_widget);
-        if (unlockWidget instanceof SlidingTab) {
-            mSlidingTab = (SlidingTab) unlockWidget;
-            mSlidingTab.setHoldAfterTrigger(true, false);
-            mSlidingTab.setLeftHintText(R.string.lockscreen_unlock_label);
-            mSlidingTab.setLeftTabResources(
+        mUnlockWidget = findViewById(R.id.unlock_widget);
+        if (mUnlockWidget instanceof SlidingTab) {
+            SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;
+            slidingTabView.setHoldAfterTrigger(true, false);
+            slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
+            slidingTabView.setLeftTabResources(
                     R.drawable.ic_jog_dial_unlock,
                     R.drawable.jog_tab_target_green,
                     R.drawable.jog_tab_bar_left_unlock,
                     R.drawable.jog_tab_left_unlock);
-            mSlidingTabMethods = new SlidingTabMethods();
-            mSlidingTab.setOnTriggerListener(mSlidingTabMethods);
-            mSlidingTabMethods.updateRightTabResources();
-        } else if (unlockWidget instanceof WaveView) {
-            mEnergyWave = (WaveView) unlockWidget;
-            mWaveViewMethods = new WaveViewMethods();
-            mEnergyWave.setOnTriggerListener(mWaveViewMethods);
-        } else if (unlockWidget instanceof MultiWaveView) {
-            mMultiWaveView = (MultiWaveView) unlockWidget;
-            mMultiWaveViewMethods = new MultiWaveViewMethods();
-            mMultiWaveViewMethods.updateResources(); // update silence/ring resources
-            mMultiWaveView.setOnTriggerListener(mMultiWaveViewMethods);
+            SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
+            slidingTabView.setOnTriggerListener(slidingTabMethods);
+            mUnlockWidgetMethods = slidingTabMethods;
+        } else if (mUnlockWidget instanceof WaveView) {
+            WaveView waveView = (WaveView) mUnlockWidget;
+            WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
+            waveView.setOnTriggerListener(waveViewMethods);
+            mUnlockWidgetMethods = waveViewMethods;
+        } else if (mUnlockWidget instanceof MultiWaveView) {
+            MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;
+            MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
+            multiWaveView.setOnTriggerListener(multiWaveViewMethods);
+            mUnlockWidgetMethods = multiWaveViewMethods;
         } else {
-            throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
+            throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);
         }
 
+        // Update widget with initial ring state
+        mUnlockWidgetMethods.updateResources();
+
+        if (DBG) Log.v(TAG, "*** LockScreen accel is "
+                + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
+
         resetStatusInfo(updateMonitor);
     }
 
@@ -540,16 +610,14 @@
      * Enables unlocking of this screen. Typically just shows the unlock widget.
      */
     private void enableUnlock() {
-        if (mEnergyWave != null) mEnergyWave.setVisibility(View.VISIBLE);
-        if (mSlidingTab != null) mSlidingTab.setVisibility(View.VISIBLE);
+        mUnlockWidgetMethods.getView().setVisibility(View.VISIBLE);
     }
 
     /**
      * Disable unlocking of this screen. Typically just hides the unlock widget.
      */
     private void disableUnlock() {
-        if (mEnergyWave != null) mEnergyWave.setVisibility(View.GONE);
-        if (mSlidingTab != null) mSlidingTab.setVisibility(View.GONE);
+        mUnlockWidgetMethods.getView().setVisibility(View.GONE);
     }
 
     /**
@@ -728,20 +796,13 @@
 
     /** {@inheritDoc} */
     public void onPause() {
-        if (mEnergyWave != null) {
-            mEnergyWave.reset();
-        }
-        if (mMultiWaveView != null) {
-            mMultiWaveView.reset(false);
-        }
+        mUnlockWidgetMethods.reset(false);
     }
 
     /** {@inheritDoc} */
     public void onResume() {
         resetStatusInfo(mUpdateMonitor);
-        if (mMultiWaveView != null) {
-            mMultiWaveView.ping();
-        }
+        mUnlockWidgetMethods.ping();
     }
 
     /** {@inheritDoc} */
@@ -757,7 +818,7 @@
         boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
         if (silent != mSilentMode) {
             mSilentMode = silent;
-            if (mSlidingTabMethods != null) mSlidingTabMethods.updateRightTabResources();
+            mUnlockWidgetMethods.updateResources();
         }
     }
 
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index 1d3e3ac..b3d7220 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -41,7 +41,7 @@
 /**
  * {@hide}
  */
-public class IntentResolver<F extends IntentFilter, R extends Object> {
+public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
     final private static String TAG = "IntentResolver";
     final private static boolean DEBUG = false;
     final private static boolean localLOGV = DEBUG || false;
@@ -333,14 +333,19 @@
         return false;
     }
 
-    protected String packageForFilter(F filter) {
-        return null;
-    }
+    /**
+     * Return the package that owns this filter.  This must be implemented to
+     * provide correct filtering of Intents that have specified a package name
+     * they are to be delivered to.
+     */
+    protected abstract String packageForFilter(F filter);
     
+    @SuppressWarnings("unchecked")
     protected R newResult(F filter, int match) {
         return (R)filter;
     }
 
+    @SuppressWarnings("unchecked")
     protected void sortResults(List<R> results) {
         Collections.sort(results, mResolvePrioritySorter);
     }
@@ -502,6 +507,7 @@
             String resolvedType, String scheme, List<F> src, List<R> dest) {
         final String action = intent.getAction();
         final Uri data = intent.getData();
+        final String packageName = intent.getPackage();
 
         final boolean excludingStopped = intent.isExcludingStopped();
 
@@ -520,6 +526,14 @@
                 continue;
             }
 
+            // Is delivery being limited to filters owned by a particular package?
+            if (packageName != null && !packageName.equals(packageForFilter(filter))) {
+                if (debug) {
+                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
+                }
+                continue;
+            }
+
             // Do we already have this one?
             if (!allowFilterResult(filter, dest)) {
                 if (debug) {
@@ -561,6 +575,7 @@
     }
 
     // Sorts a List of IntentFilter objects into descending priority order.
+    @SuppressWarnings("rawtypes")
     private static final Comparator mResolvePrioritySorter = new Comparator() {
         public int compare(Object o1, Object o2) {
             final int q1 = ((IntentFilter) o1).getPriority();
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 656ec4d..56afe7f 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -195,6 +195,7 @@
         final Object mKey;
         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
         int mPendingBroadcasts;
+        String requiredPermissions;
 
         Receiver(ILocationListener listener) {
             mListener = listener;
@@ -284,7 +285,8 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
+                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
+                                requiredPermissions);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -319,7 +321,8 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
+                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
+                                requiredPermissions);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -358,7 +361,8 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
+                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
+                                requiredPermissions);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -572,22 +576,30 @@
         return Settings.Secure.isLocationProviderEnabled(resolver, provider);
     }
 
-    private void checkPermissionsSafe(String provider) {
-        if ((LocationManager.GPS_PROVIDER.equals(provider)
-                 || LocationManager.PASSIVE_PROVIDER.equals(provider))
-            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)) {
-            throw new SecurityException("Provider " + provider
-                    + " requires ACCESS_FINE_LOCATION permission");
+    private String checkPermissionsSafe(String provider, String lastPermission) {
+        if (LocationManager.GPS_PROVIDER.equals(provider)
+                 || LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+            if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Provider " + provider
+                        + " requires ACCESS_FINE_LOCATION permission");
+            }
+            return ACCESS_FINE_LOCATION;
         }
-        if (LocationManager.NETWORK_PROVIDER.equals(provider)
-            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)
-            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)) {
-            throw new SecurityException("Provider " + provider
-                    + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
+
+        // Assume any other provider requires the coarse or fine permission.
+        if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
+                == PackageManager.PERMISSION_GRANTED) {
+            return ACCESS_FINE_LOCATION.equals(lastPermission)
+                    ? lastPermission : ACCESS_COARSE_LOCATION;
         }
+        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
+                == PackageManager.PERMISSION_GRANTED) {
+            return ACCESS_FINE_LOCATION;
+        }
+
+        throw new SecurityException("Provider " + provider
+                + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
     }
 
     private boolean isAllowedProviderSafe(String provider) {
@@ -1099,8 +1111,21 @@
         }
     }
 
+    void validatePendingIntent(PendingIntent intent) {
+        if (intent.isTargetedToPackage()) {
+            return;
+        }
+        Slog.i(TAG, "Given Intent does not require a specific package: "
+                + intent);
+        // XXX we should really throw a security exception, if the caller's
+        // targetSdkVersion is high enough.
+        //throw new SecurityException("Given Intent does not require a specific package: "
+        //        + intent);
+    }
+
     public void requestLocationUpdatesPI(String provider, Criteria criteria,
             long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
+        validatePendingIntent(intent);
         if (criteria != null) {
             // FIXME - should we consider using multiple providers simultaneously
             // rather than only the best one?
@@ -1132,7 +1157,8 @@
             throw new IllegalArgumentException("provider=" + provider);
         }
 
-        checkPermissionsSafe(provider);
+        receiver.requiredPermissions = checkPermissionsSafe(provider,
+                receiver.requiredPermissions);
 
         // so wakelock calls will succeed
         final int callingUid = Binder.getCallingUid();
@@ -1300,7 +1326,7 @@
         }
 
         // first check for permission to the provider
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
         if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
                 != PackageManager.PERMISSION_GRANTED)) {
@@ -1432,7 +1458,8 @@
                             synchronized (this) {
                                 // synchronize to ensure incrementPendingBroadcasts()
                                 // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
+                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler,
+                                        ACCESS_FINE_LOCATION);
                                 // call this after broadcasting so we do not increment
                                 // if we throw an exeption.
                                 incrementPendingBroadcasts();
@@ -1457,7 +1484,8 @@
                             synchronized (this) {
                                 // synchronize to ensure incrementPendingBroadcasts()
                                 // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
+                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler,
+                                        ACCESS_FINE_LOCATION);
                                 // call this after broadcasting so we do not increment
                                 // if we throw an exeption.
                                 incrementPendingBroadcasts();
@@ -1526,6 +1554,7 @@
 
     public void addProximityAlert(double latitude, double longitude,
         float radius, long expiration, PendingIntent intent) {
+        validatePendingIntent(intent);
         try {
             synchronized (mLock) {
                 addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
@@ -1626,7 +1655,7 @@
             return null;
         }
 
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
 
         Bundle b = new Bundle();
         b.putBoolean("network", p.requiresNetwork());
@@ -1668,7 +1697,7 @@
     }
 
     private boolean _isProviderEnabledLocked(String provider) {
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
 
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
@@ -1694,7 +1723,7 @@
     }
 
     private Location _getLastKnownLocationLocked(String provider) {
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
 
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 4ec71c1..bf877f6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -622,6 +622,11 @@
             }
             return true;
         }
+
+        @Override
+        protected String packageForFilter(BroadcastFilter filter) {
+            return filter.packageName;
+        }
     };
 
     /**
@@ -1825,6 +1830,8 @@
                 // We already have the app running, or are waiting for it to
                 // come up (we have a pid but not yet its thread), so keep it.
                 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
+                // If this is a new package in the process, add the package to the list
+                app.addPackage(info.packageName);
                 return app;
             } else {
                 // An application record is attached to a previous process,
@@ -2278,7 +2285,7 @@
             }
         }
         
-        return pir.sendInner(0, fillInIntent, resolvedType,
+        return pir.sendInner(0, fillInIntent, resolvedType, null,
                 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
     }
     
@@ -4162,6 +4169,27 @@
         return null;
     }
 
+    public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
+        if (!(pendingResult instanceof PendingIntentRecord)) {
+            return false;
+        }
+        try {
+            PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+            if (res.key.allIntents == null) {
+                return false;
+            }
+            for (int i=0; i<res.key.allIntents.length; i++) {
+                Intent intent = res.key.allIntents[i];
+                if (intent.getPackage() != null && intent.getComponent() != null) {
+                    return false;
+                }
+            }
+            return true;
+        } catch (ClassCastException e) {
+        }
+        return false;
+    }
+
     public void setProcessLimit(int max) {
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                 "setProcessLimit()");
@@ -9895,6 +9923,7 @@
         ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
         if (app != null && app.thread != null) {
             try {
+                app.addPackage(r.appInfo.packageName);
                 realStartServiceLocked(r, app);
                 return true;
             } catch (RemoteException e) {
@@ -10945,7 +10974,7 @@
         mBroadcastsScheduled = true;
     }
 
-    public Intent registerReceiver(IApplicationThread caller,
+    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter, String permission) {
         synchronized(this) {
             ProcessRecord callerApp = null;
@@ -10957,6 +10986,13 @@
                             + " (pid=" + Binder.getCallingPid()
                             + ") when registering receiver " + receiver);
                 }
+                if (callerApp.info.uid != Process.SYSTEM_UID &&
+                        !callerApp.pkgList.contains(callerPackage)) {
+                    throw new SecurityException("Given caller package " + callerPackage
+                            + " is not running in process " + callerApp);
+                }
+            } else {
+                callerPackage = null;
             }
 
             List allSticky = null;
@@ -11001,7 +11037,7 @@
                 }
                 mRegisteredReceivers.put(receiver.asBinder(), rl);
             }
-            BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
+            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
             rl.add(bf);
             if (!bf.debugCheck()) {
                 Slog.w(TAG, "==> For Dynamic broadast");
@@ -12155,6 +12191,7 @@
                     info.activityInfo.applicationInfo.uid);
             if (app != null && app.thread != null) {
                 try {
+                    app.addPackage(info.activityInfo.packageName);
                     processCurBroadcastLocked(r, app);
                     return;
                 } catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b94ee58..b1da69f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -652,6 +652,7 @@
         
         if (app != null && app.thread != null) {
             try {
+                app.addPackage(r.info.packageName);
                 realStartActivityLocked(r, app, andResume, checkConfig);
                 return;
             } catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index 2e784d3..b49bc22 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -25,12 +25,14 @@
 class BroadcastFilter extends IntentFilter {
     // Back-pointer to the list this filter is in.
     final ReceiverList receiverList;
+    final String packageName;
     final String requiredPermission;
 
     BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
-            String _requiredPermission) {
+            String _packageName, String _requiredPermission) {
         super(_filter);
         receiverList = _receiverList;
+        packageName = _packageName;
         requiredPermission = _requiredPermission;
     }
     
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index ee6e420..8ed0cc1 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -177,13 +177,13 @@
     }
 
     public int send(int code, Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver) {
+            IIntentReceiver finishedReceiver, String requiredPermission) {
         return sendInner(code, intent, resolvedType, finishedReceiver,
-                null, null, 0, 0, 0);
+                requiredPermission, null, null, 0, 0, 0);
     }
     
     int sendInner(int code, Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver,
+            IIntentReceiver finishedReceiver, String requiredPermission,
             IBinder resultTo, String resultWho, int requestCode,
             int flagsMask, int flagsValues) {
         synchronized(owner) {
@@ -246,8 +246,8 @@
                             // that the broadcast be delivered synchronously
                             owner.broadcastIntentInPackage(key.packageName, uid,
                                     finalIntent, resolvedType,
-                                    finishedReceiver, code, null, null, null,
-                                    (finishedReceiver != null), false);
+                                    finishedReceiver, code, null, null,
+                                    requiredPermission, (finishedReceiver != null), false);
                             sendFinish = false;
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index f5efda9..54bddb2 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -90,7 +90,7 @@
 
         // Reset the interface and hide the notification.
         if (mInterfaceName != null) {
-            nativeReset(mInterfaceName);
+            jniResetInterface(mInterfaceName);
             mCallback.restore();
             hideNotification();
             mInterfaceName = null;
@@ -119,7 +119,7 @@
     public void protect(ParcelFileDescriptor socket, String name) {
         try {
             mContext.enforceCallingPermission(VPN, "protect");
-            nativeProtect(socket.getFd(), name);
+            jniProtectSocket(socket.getFd(), name);
         } finally {
             try {
                 socket.close();
@@ -152,17 +152,22 @@
         }
 
         // Create and configure the interface.
-        ParcelFileDescriptor descriptor = ParcelFileDescriptor.adoptFd(
-                nativeEstablish(config.mtu, config.addresses, config.routes));
+        ParcelFileDescriptor descriptor =
+                ParcelFileDescriptor.adoptFd(jniCreateInterface(config.mtu));
 
-        // Replace the interface and abort if it fails.
+        // Abort if any of the following steps fails.
         try {
-            String interfaceName = nativeGetName(descriptor.getFd());
-
-            if (mInterfaceName != null && !mInterfaceName.equals(interfaceName)) {
-                nativeReset(mInterfaceName);
+            String name = jniGetInterfaceName(descriptor.getFd());
+            if (jniSetAddresses(name, config.addresses) < 1) {
+                throw new IllegalArgumentException("At least one address must be specified");
             }
-            mInterfaceName = interfaceName;
+            if (config.routes != null) {
+                jniSetRoutes(name, config.routes);
+            }
+            if (mInterfaceName != null && !mInterfaceName.equals(name)) {
+                jniResetInterface(mInterfaceName);
+            }
+            mInterfaceName = name;
         } catch (RuntimeException e) {
             try {
                 descriptor.close();
@@ -195,7 +200,7 @@
 
     // INetworkManagementEventObserver.Stub
     public synchronized void interfaceRemoved(String name) {
-        if (name.equals(mInterfaceName) && nativeCheck(name) == 0) {
+        if (name.equals(mInterfaceName) && jniCheckInterface(name) == 0) {
             hideNotification();
             mInterfaceName = null;
             mCallback.restore();
@@ -253,11 +258,13 @@
         }
     }
 
-    private native int nativeEstablish(int mtu, String addresses, String routes);
-    private native String nativeGetName(int fd);
-    private native void nativeReset(String name);
-    private native int nativeCheck(String name);
-    private native void nativeProtect(int fd, String name);
+    private native int jniCreateInterface(int mtu);
+    private native String jniGetInterfaceName(int fd);
+    private native int jniSetAddresses(String name, String addresses);
+    private native int jniSetRoutes(String name, String routes);
+    private native void jniResetInterface(String name);
+    private native int jniCheckInterface(String name);
+    private native void jniProtectSocket(int fd, String name);
 
     /**
      * Handle legacy VPN requests. This method stops the services and restart
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/jni/com_android_server_connectivity_Vpn.cpp
index ae7fbfe..a0ea92b 100644
--- a/services/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/jni/com_android_server_connectivity_Vpn.cpp
@@ -42,6 +42,9 @@
 namespace android
 {
 
+static int inet4 = -1;
+static int inet6 = -1;
+
 static inline in_addr_t *as_in_addr(sockaddr *sa) {
     return &((sockaddr_in *)sa)->sin_addr.s_addr;
 }
@@ -51,11 +54,9 @@
 #define SYSTEM_ERROR -1
 #define BAD_ARGUMENT -2
 
-static int create_interface(int mtu, char *name, int *index)
+static int create_interface(int mtu)
 {
-    int tun = open("/dev/tun", O_RDWR);
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-    int flags;
+    int tun = open("/dev/tun", O_RDWR | O_NONBLOCK);
 
     ifreq ifr4;
     memset(&ifr4, 0, sizeof(ifr4));
@@ -81,38 +82,45 @@
         goto error;
     }
 
-    // Get interface index.
-    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
-        LOGE("Cannot get index of %s: %s", ifr4.ifr_name, strerror(errno));
-        goto error;
-    }
-
-    // Make it non-blocking.
-    flags = fcntl(tun, F_GETFL, 0);
-    if (flags == -1 || fcntl(tun, F_SETFL, flags | O_NONBLOCK)) {
-        LOGE("Cannot set non-blocking on %s: %s", ifr4.ifr_name, strerror(errno));
-        goto error;
-    }
-
-    strcpy(name, ifr4.ifr_name);
-    *index = ifr4.ifr_ifindex;
-    close(inet4);
     return tun;
 
 error:
     close(tun);
-    close(inet4);
     return SYSTEM_ERROR;
 }
 
-static int set_addresses(const char *name, int index, const char *addresses)
+static int get_interface_name(char *name, int tun)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-    int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+    ifreq ifr4;
+    if (ioctl(tun, TUNGETIFF, &ifr4)) {
+        LOGE("Cannot get interface name: %s", strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
+    return 0;
+}
+
+static int get_interface_index(const char *name)
+{
+    ifreq ifr4;
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
+        LOGE("Cannot get index of %s: %s", name, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    return ifr4.ifr_ifindex;
+}
+
+static int set_addresses(const char *name, const char *addresses)
+{
+    int index = get_interface_index(name);
+    if (index < 0) {
+        return index;
+    }
 
     ifreq ifr4;
     memset(&ifr4, 0, sizeof(ifr4));
-    strcpy(ifr4.ifr_name, name);
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
     ifr4.ifr_addr.sa_family = AF_INET;
 
     in6_ifreq ifr6;
@@ -121,7 +129,6 @@
 
     char address[65];
     int prefix;
-
     int chars;
     int count = 0;
 
@@ -164,7 +171,7 @@
                 break;
             }
         }
-        LOGV("Address added on %s: %s/%d", name, address, prefix);
+        LOGD("Address added on %s: %s/%d", name, address, prefix);
         ++count;
     }
 
@@ -177,15 +184,15 @@
         count = BAD_ARGUMENT;
     }
 
-    close(inet4);
-    close(inet6);
     return count;
 }
 
-static int set_routes(const char *name, int index, const char *routes)
+static int set_routes(const char *name, const char *routes)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-    int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+    int index = get_interface_index(name);
+    if (index < 0) {
+        return index;
+    }
 
     rtentry rt4;
     memset(&rt4, 0, sizeof(rt4));
@@ -201,7 +208,6 @@
 
     char address[65];
     int prefix;
-
     int chars;
     int count = 0;
 
@@ -211,32 +217,50 @@
         if (strchr(address, ':')) {
             // Add an IPv6 route.
             if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
-                    prefix < 1 || prefix > 128) {
+                    prefix < 0 || prefix > 128) {
                 count = BAD_ARGUMENT;
                 break;
             }
 
-            rt6.rtmsg_dst_len = prefix;
+            rt6.rtmsg_dst_len = prefix ? prefix : 1;
             if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
             }
+
+            if (!prefix) {
+                // Split the route instead of replacing the default route.
+                rt6.rtmsg_dst.s6_addr[0] ^= 0x80;
+                if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
+                    count = SYSTEM_ERROR;
+                    break;
+                }
+            }
         } else {
             // Add an IPv4 route.
             if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
-                    prefix < 1 || prefix > 32) {
+                    prefix < 0 || prefix > 32) {
                 count = BAD_ARGUMENT;
                 break;
             }
 
-            in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
+            in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 1;
             *as_in_addr(&rt4.rt_genmask) = htonl(mask);
             if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
             }
+
+            if (!prefix) {
+                // Split the route instead of replacing the default route.
+                *as_in_addr(&rt4.rt_dst) ^= htonl(0x80000000);
+                if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
+                    count = SYSTEM_ERROR;
+                    break;
+                }
+            }
         }
-        LOGV("Route added on %s: %s/%d", name, address, prefix);
+        LOGD("Route added on %s: %s/%d", name, address, prefix);
         ++count;
     }
 
@@ -250,43 +274,24 @@
         count = BAD_ARGUMENT;
     }
 
-    close(inet4);
-    close(inet6);
     return count;
 }
 
-static int get_interface_name(char *name, int tun)
-{
-    ifreq ifr4;
-    if (ioctl(tun, TUNGETIFF, &ifr4)) {
-        LOGE("Cannot get interface name: %s", strerror(errno));
-        return SYSTEM_ERROR;
-    }
-    strcpy(name, ifr4.ifr_name);
-    return 0;
-}
-
 static int reset_interface(const char *name)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-
     ifreq ifr4;
-    ifr4.ifr_flags = 0;
     strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    ifr4.ifr_flags = 0;
 
     if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) {
         LOGE("Cannot reset %s: %s", name, strerror(errno));
-        close(inet4);
         return SYSTEM_ERROR;
     }
-    close(inet4);
     return 0;
 }
 
 static int check_interface(const char *name)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-
     ifreq ifr4;
     strncpy(ifr4.ifr_name, name, IFNAMSIZ);
     ifr4.ifr_flags = 0;
@@ -294,7 +299,6 @@
     if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) {
         LOGE("Cannot check %s: %s", name, strerror(errno));
     }
-    close(inet4);
     return ifr4.ifr_flags;
 }
 
@@ -318,86 +322,108 @@
     }
 }
 
-static jint establish(JNIEnv *env, jobject thiz,
-        jint mtu, jstring jAddresses, jstring jRoutes)
+static jint createInterface(JNIEnv *env, jobject thiz, jint mtu)
 {
-    char name[IFNAMSIZ];
-    int index;
-    int tun = create_interface(mtu, name, &index);
+    int tun = create_interface(mtu);
     if (tun < 0) {
         throwException(env, tun, "Cannot create interface");
         return -1;
     }
-    LOGD("%s is created", name);
-
-    const char *addresses;
-    const char *routes;
-    int count;
-
-    // Addresses are required.
-    addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
-    if (!addresses) {
-        jniThrowNullPointerException(env, "address");
-        goto error;
-    }
-    count = set_addresses(name, index, addresses);
-    env->ReleaseStringUTFChars(jAddresses, addresses);
-    if (count <= 0) {
-        throwException(env, count, "Cannot set address");
-        goto error;
-    }
-    LOGD("Configured %d address(es) on %s", count, name);
-
-    // Routes are optional.
-    routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
-    if (routes) {
-        count = set_routes(name, index, routes);
-        env->ReleaseStringUTFChars(jRoutes, routes);
-        if (count < 0) {
-            throwException(env, count, "Cannot set route");
-            goto error;
-        }
-        LOGD("Configured %d route(s) on %s", count, name);
-    }
-
     return tun;
-
-error:
-    close(tun);
-    LOGD("%s is destroyed", name);
-    return -1;
 }
 
-static jstring getName(JNIEnv *env, jobject thiz, jint fd)
+static jstring getInterfaceName(JNIEnv *env, jobject thiz, jint tun)
 {
     char name[IFNAMSIZ];
-    if (get_interface_name(name, fd) < 0) {
+    if (get_interface_name(name, tun) < 0) {
         throwException(env, SYSTEM_ERROR, "Cannot get interface name");
         return NULL;
     }
     return env->NewStringUTF(name);
 }
 
-static void reset(JNIEnv *env, jobject thiz, jstring jName)
+static jint setAddresses(JNIEnv *env, jobject thiz, jstring jName,
+        jstring jAddresses)
 {
-    const char *name = jName ?
-            env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *name = NULL;
+    const char *addresses = NULL;
+    int count = -1;
+
+    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        goto error;
+    }
+    addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
+    if (!addresses) {
+        jniThrowNullPointerException(env, "addresses");
+        goto error;
+    }
+    count = set_addresses(name, addresses);
+    if (count < 0) {
+        throwException(env, count, "Cannot set address");
+        count = -1;
+    }
+
+error:
+    if (name) {
+        env->ReleaseStringUTFChars(jName, name);
+    }
+    if (addresses) {
+        env->ReleaseStringUTFChars(jAddresses, addresses);
+    }
+    return count;
+}
+
+static jint setRoutes(JNIEnv *env, jobject thiz, jstring jName,
+        jstring jRoutes)
+{
+    const char *name = NULL;
+    const char *routes = NULL;
+    int count = -1;
+
+    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        goto error;
+    }
+    routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
+    if (!routes) {
+        jniThrowNullPointerException(env, "routes");
+        goto error;
+    }
+    count = set_routes(name, routes);
+    if (count < 0) {
+        throwException(env, count, "Cannot set address");
+        count = -1;
+    }
+
+error:
+    if (name) {
+        env->ReleaseStringUTFChars(jName, name);
+    }
+    if (routes) {
+        env->ReleaseStringUTFChars(jRoutes, routes);
+    }
+    return count;
+}
+
+static void resetInterface(JNIEnv *env, jobject thiz, jstring jName)
+{
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
     if (!name) {
         jniThrowNullPointerException(env, "name");
         return;
     }
     if (reset_interface(name) < 0) {
         throwException(env, SYSTEM_ERROR, "Cannot reset interface");
-    } else {
-        LOGD("%s is deactivated", name);
     }
     env->ReleaseStringUTFChars(jName, name);
 }
 
-static jint check(JNIEnv *env, jobject thiz, jstring jName)
+static jint checkInterface(JNIEnv *env, jobject thiz, jstring jName)
 {
-    const char *name = jName ?
-            env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
     if (!name) {
         jniThrowNullPointerException(env, "name");
         return 0;
@@ -407,10 +433,9 @@
     return flags;
 }
 
-static void protect(JNIEnv *env, jobject thiz, jint fd, jstring jName)
+static void protectSocket(JNIEnv *env, jobject thiz, jint fd, jstring jName)
 {
-    const char *name = jName ?
-            env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
     if (!name) {
         jniThrowNullPointerException(env, "name");
         return;
@@ -424,15 +449,23 @@
 //------------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"nativeEstablish", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)establish},
-    {"nativeGetName", "(I)Ljava/lang/String;", (void *)getName},
-    {"nativeReset", "(Ljava/lang/String;)V", (void *)reset},
-    {"nativeCheck", "(Ljava/lang/String;)I", (void *)check},
-    {"nativeProtect", "(ILjava/lang/String;)V", (void *)protect},
+    {"jniCreateInterface", "(I)I", (void *)createInterface},
+    {"jniGetInterfaceName", "(I)Ljava/lang/String;", (void *)getInterfaceName},
+    {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
+    {"jniSetRoutes", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setRoutes},
+    {"jniResetInterface", "(Ljava/lang/String;)V", (void *)resetInterface},
+    {"jniCheckInterface", "(Ljava/lang/String;)I", (void *)checkInterface},
+    {"jniProtectSocket", "(ILjava/lang/String;)V", (void *)protectSocket},
 };
 
 int register_android_server_connectivity_Vpn(JNIEnv *env)
 {
+    if (inet4 == -1) {
+        inet4 = socket(AF_INET, SOCK_DGRAM, 0);
+    }
+    if (inet6 == -1) {
+        inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+    }
     return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn",
             gMethods, NELEM(gMethods));
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1c57bc1..685613e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1799,10 +1799,10 @@
             const GLfloat h = hw_h - (hw_h * v);
             const GLfloat x = (hw_w - w) * 0.5f;
             const GLfloat y = (hw_h - h) * 0.5f;
-            vtx[0] = x;         vtx[1] = y;
-            vtx[2] = x;         vtx[3] = y + h;
-            vtx[4] = x + w;     vtx[5] = y + h;
-            vtx[6] = x + w;     vtx[7] = y;
+            vtx[0] = x;         vtx[1] = y + h;
+            vtx[2] = x;         vtx[3] = y;
+            vtx[4] = x + w;     vtx[5] = y;
+            vtx[6] = x + w;     vtx[7] = y + h;
         }
     };
 
@@ -1817,10 +1817,10 @@
             const GLfloat h = 1.0f;
             const GLfloat x = (hw_w - w) * 0.5f;
             const GLfloat y = (hw_h - h) * 0.5f;
-            vtx[0] = x;         vtx[1] = y;
-            vtx[2] = x;         vtx[3] = y + h;
-            vtx[4] = x + w;     vtx[5] = y + h;
-            vtx[6] = x + w;     vtx[7] = y;
+            vtx[0] = x;         vtx[1] = y + h;
+            vtx[2] = x;         vtx[3] = y;
+            vtx[4] = x + w;     vtx[5] = y;
+            vtx[6] = x + w;     vtx[7] = y + h;
         }
     };