Merge "Fix getHitRect() to return correct rect for transformed child"
diff --git a/Android.mk b/Android.mk
index 25c050e..c8576a0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -700,32 +700,6 @@
 
 include $(BUILD_DROIDDOC)
 
-# explicitly specify that online-sdk depends on framework-res and any generated docs
-$(full_target): framework-res-package-target
-
-# ==== docs for the s.a.c site (on the google app engine server) =======================
-# include $(CLEAR_VARS)
-
-# LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
-# LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
-# LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
-# LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
-# LOCAL_DROIDDOC_HTML_DIR:=../../docs/source.android.com/src
-# LOCAL_ADDITIONAL_HTML_DIR:=
-# LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
-# LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
-# LOCAL_MODULE := online-sac
-#
-# LOCAL_DROIDDOC_OPTIONS:= \
-#		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-#		-toroot / \
-#		-hdf android.whichdoc online \
-#		-hdf sac true
-#
-# LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
-#
-# include $(BUILD_DROIDDOC)
-
 # ==== docs for the web (on the devsite app engine server) =======================
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
@@ -754,35 +728,6 @@
 
 include $(BUILD_DROIDDOC)
 
-# explicitly specify that ds depends on framework-res and any generated docs
-$(full_target): framework-res-package-target
-
-#==== reference docs for GCM =======================
-
-include $(CLEAR_VARS)
-#
-gcm_docs_src_files += \
-        $(call all-java-files-under, ../../vendor/unbundled_google/libs/gcm/gcm-client/src) \
-        $(call all-java-files-under, ../../vendor/unbundled_google/libs/gcm/gcm-server/src) \
-        $(call all-html-files-under, ../../vendor/unbundled_google/libs/gcm/gcm-client/src) \
-        $(call all-html-files-under, ../../vendor/unbundled_google/libs/gcm/gcm-server/src) \
-
-LOCAL_SRC_FILES := $(gcm_docs_src_files)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE:= online-gcm-ref
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_IS_HOST_MODULE := false
-
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-sdk
-
-LOCAL_DROIDDOC_OPTIONS := \
-        -toroot / \
-        -gcmref \
-        -hdf android.whichdoc online \
-        -hdf template.showLanguageMenu true
-
-include $(BUILD_DROIDDOC)
-
 # ==== docs that have all of the stuff that's @hidden =======================
 include $(CLEAR_VARS)
 
diff --git a/api/current.txt b/api/current.txt
index c8f999f..ee4732d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4153,11 +4153,14 @@
   }
 
   public final class UiAutomation {
-    method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, com.android.internal.util.Predicate<android.view.accessibility.AccessibilityEvent>, long) throws java.util.concurrent.TimeoutException;
+    method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
+    method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
     method public boolean injectInputEvent(android.view.InputEvent, boolean);
+    method public final boolean performGlobalAction(int);
     method public void setOnAccessibilityEventListener(android.app.UiAutomation.OnAccessibilityEventListener);
     method public boolean setRotation(int);
+    method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
     method public android.graphics.Bitmap takeScreenshot();
     method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
     field public static final int ROTATION_FREEZE_0 = 0; // 0x0
@@ -4168,6 +4171,10 @@
     field public static final int ROTATION_UNFREEZE = -2; // 0xfffffffe
   }
 
+  public static abstract interface UiAutomation.AccessibilityEventFilter {
+    method public abstract boolean accept(android.view.accessibility.AccessibilityEvent);
+  }
+
   public static abstract interface UiAutomation.OnAccessibilityEventListener {
     method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
   }
@@ -19485,6 +19492,7 @@
 
   public class FieldPacker {
     ctor public FieldPacker(int);
+    ctor public FieldPacker(byte[]);
     method public void addBoolean(boolean);
     method public void addF32(float);
     method public void addF32(android.renderscript.Float2);
@@ -22265,6 +22273,21 @@
     method public int getTopPadding();
   }
 
+  public abstract interface TextDirectionHeuristic {
+    method public abstract boolean isRtl(char[], int, int);
+    method public abstract boolean isRtl(java.lang.CharSequence, int, int);
+  }
+
+  public class TextDirectionHeuristics {
+    ctor public TextDirectionHeuristics();
+    field public static final android.text.TextDirectionHeuristic ANYRTL_LTR;
+    field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_LTR;
+    field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_RTL;
+    field public static final android.text.TextDirectionHeuristic LOCALE;
+    field public static final android.text.TextDirectionHeuristic LTR;
+    field public static final android.text.TextDirectionHeuristic RTL;
+  }
+
   public class TextPaint extends android.graphics.Paint {
     ctor public TextPaint();
     ctor public TextPaint(int);
@@ -22356,6 +22379,48 @@
 
 }
 
+package android.text.bidi {
+
+  public final class BidiFormatter {
+    method public java.lang.String dirAttr(java.lang.String);
+    method public java.lang.String dirAttr(java.lang.String, android.text.TextDirectionHeuristic);
+    method public java.lang.String dirAttr(boolean);
+    method public java.lang.String dirAttrValue(java.lang.String);
+    method public java.lang.String dirAttrValue(java.lang.String, android.text.TextDirectionHeuristic);
+    method public java.lang.String dirAttrValue(boolean);
+    method public java.lang.String endEdge();
+    method public static android.text.bidi.BidiFormatter getInstance(boolean);
+    method public static android.text.bidi.BidiFormatter getInstance(java.util.Locale);
+    method public boolean getStereoReset();
+    method public boolean isRtl(java.lang.String);
+    method public boolean isRtlContext();
+    method public java.lang.String mark();
+    method public java.lang.String markAfter(java.lang.String);
+    method public java.lang.String markAfter(java.lang.String, android.text.TextDirectionHeuristic);
+    method public java.lang.String markBefore(java.lang.String);
+    method public java.lang.String markBefore(java.lang.String, android.text.TextDirectionHeuristic);
+    method public java.lang.String spanWrap(java.lang.String, android.text.TextDirectionHeuristic, boolean);
+    method public java.lang.String spanWrap(java.lang.String, android.text.TextDirectionHeuristic);
+    method public java.lang.String spanWrap(java.lang.String, boolean);
+    method public java.lang.String spanWrap(java.lang.String);
+    method public java.lang.String startEdge();
+    method public java.lang.String unicodeWrap(java.lang.String, android.text.TextDirectionHeuristic, boolean);
+    method public java.lang.String unicodeWrap(java.lang.String, android.text.TextDirectionHeuristic);
+    method public java.lang.String unicodeWrap(java.lang.String, boolean);
+    method public java.lang.String unicodeWrap(java.lang.String);
+  }
+
+  public static final class BidiFormatter.Builder {
+    ctor public BidiFormatter.Builder();
+    ctor public BidiFormatter.Builder(boolean);
+    ctor public BidiFormatter.Builder(java.util.Locale);
+    method public android.text.bidi.BidiFormatter build();
+    method public android.text.bidi.BidiFormatter.Builder setTextDirectionHeuristic(android.text.TextDirectionHeuristic);
+    method public android.text.bidi.BidiFormatter.Builder stereoReset(boolean);
+  }
+
+}
+
 package android.text.format {
 
   public class DateFormat {
@@ -23278,6 +23343,7 @@
     field public static final int DENSITY_TV = 213; // 0xd5
     field public static final int DENSITY_XHIGH = 320; // 0x140
     field public static final int DENSITY_XXHIGH = 480; // 0x1e0
+    field public static final int DENSITY_XXXHIGH = 640; // 0x280
     field public float density;
     field public int densityDpi;
     field public int heightPixels;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8dddbc1..811b92a 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -457,7 +457,7 @@
      *
      * @return The accessibility service info.
      *
-     * @see AccessibilityNodeInfo
+     * @see AccessibilityServiceInfo
      */
     public final AccessibilityServiceInfo getServiceInfo() {
         IAccessibilityServiceConnection connection =
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 594be68..944a533 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1915,7 +1915,30 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
-    /** @hide */
+    /**
+     * @hide
+     * Helper for dealing with incoming user arguments to system service calls.
+     * Takes care of checking permissions and converting USER_CURRENT to the
+     * actual current user.
+     *
+     * @param callingPid The pid of the incoming call, as per Binder.getCallingPid().
+     * @param callingUid The uid of the incoming call, as per Binder.getCallingUid().
+     * @param userId The user id argument supplied by the caller -- this is the user
+     * they want to run as.
+     * @param allowAll If true, we will allow USER_ALL.  This means you must be prepared
+     * to get a USER_ALL returned and deal with it correctly.  If false,
+     * an exception will be thrown if USER_ALL is supplied.
+     * @param requireFull If true, the caller must hold
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} to be able to run as a
+     * different user than their current process; otherwise they must hold
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
+     * @param name Optional textual name of the incoming call; only for generating error messages.
+     * @param callerPackage Optional package name of caller; only for error messages.
+     *
+     * @return Returns the user ID that the call should run as.  Will always be a concrete
+     * user number, unless <var>allowAll</var> is true in which case it could also be
+     * USER_ALL.
+     */
     public static int handleIncomingUser(int callingPid, int callingUid, int userId,
             boolean allowAll, boolean requireFull, String name, String callerPackage) {
         if (UserHandle.getUserId(callingUid) == userId) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 34708ab..de69867 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.Manifest;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IAppOpsCallback;
 
@@ -29,7 +30,25 @@
 import android.os.Process;
 import android.os.RemoteException;
 
-/** @hide */
+/**
+ * API for interacting with "application operation" tracking.  Allows you to:
+ *
+ * - Note when operations are happening, and find out if they are allowed for the current caller.
+ * - Disallow specific apps from doing specific operations.
+ * - Collect all of the current information about operations that have been executed or are not
+ * being allowed.
+ * - Monitor for changes in whether an operation is allowed.
+ *
+ * Each operation is identified by a single integer; these integers are a fixed set of
+ * operations, enumerated by the OP_* constants.
+ *
+ * When checking operations, the result is a "mode" integer indicating the current setting
+ * for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but
+ * fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (through a
+ * SecurityException back to the caller; the normal operation calls will do this for you).
+ *
+ * @hide
+ */
 public class AppOpsManager {
     final Context mContext;
     final IAppOpsService mService;
@@ -71,8 +90,11 @@
     public static final int OP_WRITE_SETTINGS = 23;
     public static final int OP_SYSTEM_ALERT_WINDOW = 24;
     public static final int OP_ACCESS_NOTIFICATIONS = 25;
+    public static final int OP_CAMERA = 26;
+    public static final int OP_RECORD_AUDIO = 27;
+    public static final int OP_PLAY_AUDIO = 28;
     /** @hide */
-    public static final int _NUM_OP = 26;
+    public static final int _NUM_OP = 29;
 
     /**
      * This maps each operation to the operation that serves as the
@@ -109,6 +131,9 @@
             OP_WRITE_SETTINGS,
             OP_SYSTEM_ALERT_WINDOW,
             OP_ACCESS_NOTIFICATIONS,
+            OP_CAMERA,
+            OP_RECORD_AUDIO,
+            OP_PLAY_AUDIO,
     };
 
     /**
@@ -142,6 +167,9 @@
             "WRITE_SETTINGS",
             "SYSTEM_ALERT_WINDOW",
             "ACCESS_NOTIFICATIONS",
+            "CAMERA",
+            "RECORD_AUDIO",
+            "PLAY_AUDIO",
     };
 
     /**
@@ -175,21 +203,36 @@
             android.Manifest.permission.WRITE_SETTINGS,
             android.Manifest.permission.SYSTEM_ALERT_WINDOW,
             android.Manifest.permission.ACCESS_NOTIFICATIONS,
+            android.Manifest.permission.CAMERA,
+            android.Manifest.permission.RECORD_AUDIO,
+            null, // no permission for playing audio
     };
 
+    /**
+     * Retrieve the op switch that controls the given operation.
+     */
     public static int opToSwitch(int op) {
         return sOpToSwitch[op];
     }
 
+    /**
+     * Retrieve a non-localized name for the operation, for debugging output.
+     */
     public static String opToName(int op) {
         if (op == OP_NONE) return "NONE";
         return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
     }
 
+    /**
+     * Retrieve the permission associated with an operation, or null if there is not one.
+     */
     public static String opToPermission(int op) {
         return sOpPerms[op];
     }
 
+    /**
+     * Class holding all of the operation information associated with an app.
+     */
     public static class PackageOps implements Parcelable {
         private final String mPackageName;
         private final int mUid;
@@ -249,6 +292,9 @@
         };
     }
 
+    /**
+     * Class holding the information about one unique operation of an application.
+     */
     public static class OpEntry implements Parcelable {
         private final int mOp;
         private final int mMode;
@@ -321,6 +367,9 @@
         };
     }
 
+    /**
+     * Callback for notification of changes to operation state.
+     */
     public interface Callback {
         public void opChanged(int op, String packageName);
     }
@@ -330,6 +379,11 @@
         mService = service;
     }
 
+    /**
+     * Retrieve current operation state for all applications.
+     *
+     * @param ops The set of operations you are interested in, or null if you want all of them.
+     */
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
         try {
             return mService.getPackagesForOps(ops);
@@ -338,6 +392,13 @@
         return null;
     }
 
+    /**
+     * Retrieve current operation state for one application.
+     *
+     * @param uid The uid of the application of interest.
+     * @param packageName The name of the application of interest.
+     * @param ops The set of operations you are interested in, or null if you want all of them.
+     */
     public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
         try {
             return mService.getOpsForPackage(uid, packageName, ops);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bb10f62..1f4c81d 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -38,5 +38,6 @@
     boolean areNotificationsEnabledForPackage(String pkg, int uid);
 
     StatusBarNotification[] getActiveNotifications(String callingPkg);
+    StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count);
 }
 
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index e611f6d..7d02342 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -18,7 +18,9 @@
 
 import android.accessibilityservice.AccessibilityService.Callbacks;
 import android.accessibilityservice.AccessibilityService.IAccessibilityServiceClientWrapper;
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceClient;
+import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Point;
@@ -35,8 +37,6 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
 
-import com.android.internal.util.Predicate;
-
 import java.util.ArrayList;
 import java.util.concurrent.TimeoutException;
 
@@ -45,7 +45,10 @@
  * introspection of the screen content. It relies on the platform accessibility
  * APIs to introspect the screen and to perform some actions on the remote view
  * tree. It also allows injecting of arbitrary raw input events simulating user
- * interaction with keyboards and touch devices.
+ * interaction with keyboards and touch devices. One can think of a UiAutomation
+ * as a special type of {@link android.accessibilityservice.AccessibilityService}
+ * which does not provide hooks for the service life cycle and exposes other
+ * APIs that are useful for UI test automation.
  * <p>
  * The APIs exposed by this class are low-level to maximize flexibility when
  * developing UI test automation tools and libraries. Generally, a UiAutomation
@@ -130,6 +133,21 @@
     }
 
     /**
+     * Listener for filtering accessibility events.
+     */
+    public static interface AccessibilityEventFilter {
+
+        /**
+         * Callback for determining whether an event is accepted or
+         * it is filtered out.
+         *
+         * @param event The event to process.
+         * @return True if the event is accepted, false to filter it out.
+         */
+        public boolean accept(AccessibilityEvent event);
+    }
+
+    /**
      * Creates a new instance that will handle callbacks from the accessibility
      * layer on the thread of the provided looper and perform requests for privileged
      * operations on the provided connection.
@@ -243,6 +261,90 @@
     }
 
     /**
+     * Performs a global action. Such an action can be performed at any moment
+     * regardless of the current application or user location in that application.
+     * For example going back, going home, opening recents, etc.
+     *
+     * @param action The action to perform.
+     * @return Whether the action was successfully performed.
+     *
+     * @see AccessibilityService#GLOBAL_ACTION_BACK
+     * @see AccessibilityService#GLOBAL_ACTION_HOME
+     * @see AccessibilityService#GLOBAL_ACTION_NOTIFICATIONS
+     * @see AccessibilityService#GLOBAL_ACTION_RECENTS
+     */
+    public final boolean performGlobalAction(int action) {
+        final IAccessibilityServiceConnection connection;
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+            connection = AccessibilityInteractionClient.getInstance()
+                    .getConnection(mConnectionId);
+        }
+        // Calling out without a lock held.
+        if (connection != null) {
+            try {
+                return connection.performGlobalAction(action);
+            } catch (RemoteException re) {
+                Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Gets the an {@link AccessibilityServiceInfo} describing this UiAutomation.
+     * This method is useful if one wants to change some of the dynamically
+     * configurable properties at runtime.
+     *
+     * @return The accessibility service info.
+     *
+     * @see AccessibilityServiceInfo
+     */
+    public final AccessibilityServiceInfo getServiceInfo() {
+        final IAccessibilityServiceConnection connection;
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+            connection = AccessibilityInteractionClient.getInstance()
+                    .getConnection(mConnectionId);
+        }
+        // Calling out without a lock held.
+        if (connection != null) {
+            try {
+                return connection.getServiceInfo();
+            } catch (RemoteException re) {
+                Log.w(LOG_TAG, "Error while getting AccessibilityServiceInfo", re);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Sets the {@link AccessibilityServiceInfo} that describes how this
+     * UiAutomation will be handled by the platform accessibility layer.
+     *
+     * @param info The info.
+     *
+     * @see AccessibilityServiceInfo
+     */
+    public final void setServiceInfo(AccessibilityServiceInfo info) {
+        final IAccessibilityServiceConnection connection;
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+            AccessibilityInteractionClient.getInstance().clearCache();
+            connection = AccessibilityInteractionClient.getInstance()
+                    .getConnection(mConnectionId);
+        }
+        // Calling out without a lock held.
+        if (connection != null) {
+            try {
+                connection.setServiceInfo(info);
+            } catch (RemoteException re) {
+                Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
+            }
+        }
+    }
+
+    /**
      * Gets the root {@link AccessibilityNodeInfo} in the active window.
      *
      * @return The root info.
@@ -339,7 +441,7 @@
      * @throws TimeoutException If the expected event is not received within the timeout.
      */
     public AccessibilityEvent executeAndWaitForEvent(Runnable command,
-            Predicate<AccessibilityEvent> filter, long timeoutMillis) throws TimeoutException {
+            AccessibilityEventFilter filter, long timeoutMillis) throws TimeoutException {
         synchronized (mLock) {
             throwIfNotConnectedLocked();
 
@@ -363,7 +465,7 @@
                         if (event.getEventTime() <= executionStartTimeMillis) {
                             continue;
                         }
-                        if (filter.apply(event)) {
+                        if (filter.accept(event)) {
                             return event;
                         }
                         event.recycle();
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 09ff7be..028317f 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -703,7 +703,13 @@
      * show for the initial UI.
      */
     public Header onGetInitialHeader() {
-        return mHeaders.get(0);
+        for (int i=0; i<mHeaders.size(); i++) {
+            Header h = mHeaders.get(i);
+            if (h.fragment != null) {
+                return h;
+            }
+        }
+        throw new IllegalStateException("Must have at least one header with a fragment");
     }
 
     /**
@@ -1167,6 +1173,9 @@
             getFragmentManager().popBackStack(BACK_STACK_PREFS,
                     FragmentManager.POP_BACK_STACK_INCLUSIVE);
         } else {
+            if (header.fragment == null) {
+                throw new IllegalStateException("can't switch to header that has no fragment");
+            }
             int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
             switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
             setSelectedHeader(header);
diff --git a/core/java/android/text/TextDirectionHeuristic.java b/core/java/android/text/TextDirectionHeuristic.java
index 513e11c..8a4ba42 100644
--- a/core/java/android/text/TextDirectionHeuristic.java
+++ b/core/java/android/text/TextDirectionHeuristic.java
@@ -17,10 +17,30 @@
 package android.text;
 
 /**
- * Interface for objects that guess at the paragraph direction by examining text.
- *
- * @hide
+ * Interface for objects that use a heuristic for guessing at the paragraph direction by examining text.
  */
 public interface TextDirectionHeuristic {
-    boolean isRtl(char[] text, int start, int count);
+    /**
+     * Guess if a chars array is in the RTL direction or not.
+     *
+     * @param array the char array.
+     * @param start start index, inclusive.
+     * @param count the length to check, must not be negative and not greater than
+     *          {@code array.length - start}.
+     * @return true if all chars in the range are to be considered in a RTL direction,
+     *          false otherwise.
+     */
+    boolean isRtl(char[] array, int start, int count);
+
+    /**
+     * Guess if a {@code CharSequence} is in the RTL direction or not.
+     *
+     * @param cs the CharSequence.
+     * @param start start index, inclusive.
+     * @param count the length to check, must not be negative and not greater than
+     *            {@code CharSequence.length() - start}.
+     * @return true if all chars in the range are to be considered in a RTL direction,
+     *          false otherwise.
+     */
+    boolean isRtl(CharSequence cs, int start, int count);
 }
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index df8c4c6..7d7e3a9 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -19,43 +19,45 @@
 
 import android.view.View;
 
+import java.nio.CharBuffer;
+
 /**
  * Some objects that implement TextDirectionHeuristic.
  *
- * @hide
  */
 public class TextDirectionHeuristics {
 
-    /** Always decides that the direction is left to right. */
+    /**
+     * Always decides that the direction is left to right.
+     */
     public static final TextDirectionHeuristic LTR =
         new TextDirectionHeuristicInternal(null /* no algorithm */, false);
 
-    /** Always decides that the direction is right to left. */
+    /**
+     * Always decides that the direction is right to left.
+     */
     public static final TextDirectionHeuristic RTL =
         new TextDirectionHeuristicInternal(null /* no algorithm */, true);
 
     /**
-     * Determines the direction based on the first strong directional character,
-     * including bidi format chars, falling back to left to right if it
-     * finds none.  This is the default behavior of the Unicode Bidirectional
-     * Algorithm.
+     * Determines the direction based on the first strong directional character, including bidi
+     * format chars, falling back to left to right if it finds none. This is the default behavior
+     * of the Unicode Bidirectional Algorithm.
      */
     public static final TextDirectionHeuristic FIRSTSTRONG_LTR =
         new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, false);
 
     /**
-     * Determines the direction based on the first strong directional character,
-     * including bidi format chars, falling back to right to left if it
-     * finds none.  This is similar to the default behavior of the Unicode
-     * Bidirectional Algorithm, just with different fallback behavior.
+     * Determines the direction based on the first strong directional character, including bidi
+     * format chars, falling back to right to left if it finds none. This is similar to the default
+     * behavior of the Unicode Bidirectional Algorithm, just with different fallback behavior.
      */
     public static final TextDirectionHeuristic FIRSTSTRONG_RTL =
         new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);
 
     /**
-     * If the text contains any strong right to left non-format character, determines
-     * that the direction is right to left, falling back to left to right if it
-     * finds none.
+     * If the text contains any strong right to left non-format character, determines that the
+     * direction is right to left, falling back to left to right if it finds none.
      */
     public static final TextDirectionHeuristic ANYRTL_LTR =
         new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
@@ -65,8 +67,39 @@
      */
     public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
 
-    private static enum TriState {
-        TRUE, FALSE, UNKNOWN;
+    /**
+     * State constants for taking care about true / false / unknown
+     */
+    private static final int STATE_TRUE = 0;
+    private static final int STATE_FALSE = 1;
+    private static final int STATE_UNKNOWN = 2;
+
+    private static int isRtlText(int directionality) {
+        switch (directionality) {
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+                return STATE_FALSE;
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+                return STATE_TRUE;
+            default:
+                return STATE_UNKNOWN;
+        }
+    }
+
+    private static int isRtlTextOrFormat(int directionality) {
+        switch (directionality) {
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+                return STATE_FALSE;
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
+            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+                return STATE_TRUE;
+            default:
+                return STATE_UNKNOWN;
+        }
     }
 
     /**
@@ -87,21 +120,26 @@
         abstract protected boolean defaultIsRtl();
 
         @Override
-        public boolean isRtl(char[] chars, int start, int count) {
-            if (chars == null || start < 0 || count < 0 || chars.length - count < start) {
+        public boolean isRtl(char[] array, int start, int count) {
+            return isRtl(CharBuffer.wrap(array), start, count);
+        }
+
+        @Override
+        public boolean isRtl(CharSequence cs, int start, int count) {
+            if (cs == null || start < 0 || count < 0 || cs.length() - count < start) {
                 throw new IllegalArgumentException();
             }
             if (mAlgorithm == null) {
                 return defaultIsRtl();
             }
-            return doCheck(chars, start, count);
+            return doCheck(cs, start, count);
         }
 
-        private boolean doCheck(char[] chars, int start, int count) {
-            switch(mAlgorithm.checkRtl(chars, start, count)) {
-                case TRUE:
+        private boolean doCheck(CharSequence cs, int start, int count) {
+            switch(mAlgorithm.checkRtl(cs, start, count)) {
+                case STATE_TRUE:
                     return true;
-                case FALSE:
+                case STATE_FALSE:
                     return false;
                 default:
                     return defaultIsRtl();
@@ -124,58 +162,26 @@
         }
     }
 
-    private static TriState isRtlText(int directionality) {
-        switch (directionality) {
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-                return TriState.FALSE;
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
-                return TriState.TRUE;
-            default:
-                return TriState.UNKNOWN;
-        }
-    }
-
-    private static TriState isRtlTextOrFormat(int directionality) {
-        switch (directionality) {
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
-                return TriState.FALSE;
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
-            case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
-                return TriState.TRUE;
-            default:
-                return TriState.UNKNOWN;
-        }
-    }
-
     /**
      * Interface for an algorithm to guess the direction of a paragraph of text.
-     *
      */
     private static interface TextDirectionAlgorithm {
         /**
          * Returns whether the range of text is RTL according to the algorithm.
-         *
          */
-        TriState checkRtl(char[] text, int start, int count);
+        int checkRtl(CharSequence cs, int start, int count);
     }
 
     /**
-     * Algorithm that uses the first strong directional character to determine
-     * the paragraph direction.  This is the standard Unicode Bidirectional
-     * algorithm.
-     *
+     * Algorithm that uses the first strong directional character to determine the paragraph
+     * direction. This is the standard Unicode Bidirectional algorithm.
      */
     private static class FirstStrong implements TextDirectionAlgorithm {
         @Override
-        public TriState checkRtl(char[] text, int start, int count) {
-            TriState result = TriState.UNKNOWN;
-            for (int i = start, e = start + count; i < e && result == TriState.UNKNOWN; ++i) {
-                result = isRtlTextOrFormat(Character.getDirectionality(text[i]));
+        public int checkRtl(CharSequence cs, int start, int count) {
+            int result = STATE_UNKNOWN;
+            for (int i = start, e = start + count; i < e && result == STATE_UNKNOWN; ++i) {
+                result = isRtlTextOrFormat(Character.getDirectionality(cs.charAt(i)));
             }
             return result;
         }
@@ -190,25 +196,24 @@
      * Algorithm that uses the presence of any strong directional non-format
      * character (e.g. excludes LRE, LRO, RLE, RLO) to determine the
      * direction of text.
-     *
      */
     private static class AnyStrong implements TextDirectionAlgorithm {
         private final boolean mLookForRtl;
 
         @Override
-        public TriState checkRtl(char[] text, int start, int count) {
+        public int checkRtl(CharSequence cs, int start, int count) {
             boolean haveUnlookedFor = false;
             for (int i = start, e = start + count; i < e; ++i) {
-                switch (isRtlText(Character.getDirectionality(text[i]))) {
-                    case TRUE:
+                switch (isRtlText(Character.getDirectionality(cs.charAt(i)))) {
+                    case STATE_TRUE:
                         if (mLookForRtl) {
-                            return TriState.TRUE;
+                            return STATE_TRUE;
                         }
                         haveUnlookedFor = true;
                         break;
-                    case FALSE:
+                    case STATE_FALSE:
                         if (!mLookForRtl) {
-                            return TriState.FALSE;
+                            return STATE_FALSE;
                         }
                         haveUnlookedFor = true;
                         break;
@@ -217,9 +222,9 @@
                 }
             }
             if (haveUnlookedFor) {
-                return mLookForRtl ? TriState.FALSE : TriState.TRUE;
+                return mLookForRtl ? STATE_FALSE : STATE_TRUE;
             }
-            return TriState.UNKNOWN;
+            return STATE_UNKNOWN;
         }
 
         private AnyStrong(boolean lookForRtl) {
diff --git a/core/java/android/text/bidi/BidiFormatter.java b/core/java/android/text/bidi/BidiFormatter.java
new file mode 100644
index 0000000..370cbf7
--- /dev/null
+++ b/core/java/android/text/bidi/BidiFormatter.java
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.bidi;
+
+import android.text.TextDirectionHeuristic;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.view.View;
+
+import static android.text.TextDirectionHeuristics.FIRSTSTRONG_LTR;
+
+import java.util.Locale;
+
+
+/**
+ * Utility class for formatting text for display in a potentially opposite-directionality context
+ * without garbling. The directionality of the context is set at formatter creation and the
+ * directionality of the text can be either estimated or passed in when known. Provides the
+ * following functionality:
+ * <p>
+ * 1. Bidi Wrapping
+ * When text in one language is mixed into a document in another, opposite-directionality language,
+ * e.g. when an English business name is embedded in a Hebrew web page, both the inserted string
+ * and the text surrounding it may be displayed incorrectly unless the inserted string is explicitly
+ * separated from the surrounding text in a "wrapper" that:
+ * <p>
+ * - Declares its directionality so that the string is displayed correctly. This can be done in HTML
+ *   markup (e.g. a 'span dir="rtl"' element) by {@link #spanWrap} and similar methods, or - only in
+ *   contexts where markup can't be used - in Unicode bidi formatting codes by {@link #unicodeWrap}
+ *   and similar methods.
+ * <p>
+ * - Isolates the string's directionality, so it does not unduly affect the surrounding content.
+ *   Currently, this can only be done using invisible Unicode characters of the same direction as
+ *   the context (LRM or RLM) in addition to the directionality declaration above, thus "resetting"
+ *   the directionality to that of the context. The "reset" may need to be done at both ends of the
+ *   string. Without "reset" after the string, the string will "stick" to a number or logically
+ *   separate opposite-direction text that happens to follow it in-line (even if separated by
+ *   neutral content like spaces and punctuation). Without "reset" before the string, the same can
+ *   happen there, but only with more opposite-direction text, not a number. One approach is to
+ *   "reset" the direction only after each string, on the theory that if the preceding opposite-
+ *   direction text is itself bidi-wrapped, the "reset" after it will prevent the sticking. (Doing
+ *   the "reset" only before each string definitely does not work because we do not want to require
+ *   bidi-wrapping numbers, and a bidi-wrapped opposite-direction string could be followed by a
+ *   number.) Still, the safest policy is to do the "reset" on both ends of each string, since RTL
+ *   message translations often contain untranslated Latin-script brand names and technical terms,
+ *   and one of these can be followed by a bidi-wrapped inserted value. On the other hand, when one
+ *   has such a message, it is best to do the "reset" manually in the message translation itself,
+ *   since the message's opposite-direction text could be followed by an inserted number, which we
+ *   would not bidi-wrap anyway. Thus, "reset" only after the string is the current default. In an
+ *   alternative to "reset", recent additions to the HTML, CSS, and Unicode standards allow the
+ *   isolation to be part of the directionality declaration. This form of isolation is better than
+ *   "reset" because it takes less space, does not require knowing the context directionality, has a
+ *   gentler effect than "reset", and protects both ends of the string. However, we do not yet allow
+ *   using it because required platforms do not yet support it.
+ * <p>
+ * Providing these wrapping services is the basic purpose of the bidi formatter.
+ * <p>
+ * 2. Directionality estimation
+ * How does one know whether a string about to be inserted into surrounding text has the same
+ * directionality? Well, in many cases, one knows that this must be the case when writing the code
+ * doing the insertion, e.g. when a localized message is inserted into a localized page. In such
+ * cases there is no need to involve the bidi formatter at all. In some other cases, it need not be
+ * the same as the context, but is either constant (e.g. urls are always LTR) or otherwise known.
+ * In the remaining cases, e.g. when the string is user-entered or comes from a database, the
+ * language of the string (and thus its directionality) is not known a priori, and must be
+ * estimated at run-time. The bidi formatter can do this automatically using the default
+ * first-strong estimation algorithm. It can also be configured to use a custom directionality
+ * estimation object.
+ * <p>
+ * 3. Escaping
+ * When wrapping plain text - i.e. text that is not already HTML or HTML-escaped - in HTML markup,
+ * the text must first be HTML-escaped to prevent XSS attacks and other nasty business. This of
+ * course is always true, but the escaping can not be done after the string has already been wrapped
+ * in markup, so the bidi formatter also serves as a last chance and includes escaping services.
+ * <p>
+ * Thus, in a single call, the formatter will escape the input string as specified, determine its
+ * directionality, and wrap it as necessary. It is then up to the caller to insert the return value
+ * in the output.
+ */
+public final class BidiFormatter {
+
+    /**
+     * The default text direction heuristic.
+     */
+    private static TextDirectionHeuristic DEFAULT_TEXT_DIRECTION_HEURISTIC = FIRSTSTRONG_LTR;
+
+    /**
+     * Unicode "Left-To-Right Embedding" (LRE) character.
+     */
+    private static final char LRE = '\u202A';
+
+    /**
+     * Unicode "Right-To-Left Embedding" (RLE) character.
+     */
+    private static final char RLE = '\u202B';
+
+    /**
+     * Unicode "Pop Directional Formatting" (PDF) character.
+     */
+    private static final char PDF = '\u202C';
+
+    /**
+     *  Unicode "Left-To-Right Mark" (LRM) character.
+     */
+    private static final char LRM = '\u200E';
+
+    /*
+     * Unicode "Right-To-Left Mark" (RLM) character.
+     */
+    private static final char RLM = '\u200F';
+
+    /*
+     * String representation of LRM
+     */
+    private static final String LRM_STRING = Character.toString(LRM);
+
+    /*
+     * String representation of RLM
+     */
+    private static final String RLM_STRING = Character.toString(RLM);
+
+    /**
+     * "ltr" string constant.
+     */
+    private static final String LTR_STRING = "ltr";
+
+    /**
+     * "rtl" string constant.
+     */
+    private static final String RTL_STRING = "rtl";
+
+    /**
+     * "dir=\"ltr\"" string constant.
+     */
+    private static final String DIR_LTR_STRING = "dir=\"ltr\"";
+
+    /**
+     * "dir=\"rtl\"" string constant.
+     */
+    private static final String DIR_RTL_STRING = "dir=\"rtl\"";
+
+    /**
+     * "right" string constant.
+     */
+    private static final String RIGHT = "right";
+
+    /**
+     * "left" string constant.
+     */
+    private static final String LEFT = "left";
+
+    /**
+     * Empty string constant.
+     */
+    private static final String EMPTY_STRING = "";
+
+    /**
+     * A class for building a BidiFormatter with non-default options.
+     */
+    public static final class Builder {
+        private boolean isRtlContext;
+        private int flags;
+        private TextDirectionHeuristic textDirectionHeuristic;
+
+        /**
+         * Constructor.
+         *
+         */
+        public Builder() {
+            initialize(isRtlLocale(Locale.getDefault()));
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param rtlContext Whether the context directionality is RTL.
+         */
+        public Builder(boolean rtlContext) {
+            initialize(rtlContext);
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param locale The context locale.
+         */
+        public Builder(Locale locale) {
+            initialize(isRtlLocale(locale));
+        }
+
+        /**
+         * Initializes the builder with the given context directionality and default options.
+         *
+         * @param isRtlContext Whether the context is RTL or not.
+         */
+        private void initialize(boolean isRtlContext) {
+            this.isRtlContext = isRtlContext;
+            textDirectionHeuristic = DEFAULT_TEXT_DIRECTION_HEURISTIC;
+            this.flags = DEFAULT_FLAGS;
+        }
+
+        /**
+         * Specifies whether the BidiFormatter to be built should also "reset" directionality before
+         * a string being bidi-wrapped, not just after it. The default is false.
+         */
+        public Builder stereoReset(boolean stereoReset) {
+            if (stereoReset) {
+                flags |= FLAG_STEREO_RESET;
+            } else {
+                flags &= ~FLAG_STEREO_RESET;
+            }
+            return this;
+        }
+
+        /**
+         * Specifies the default directionality estimation algorithm to be used by the BidiFormatter.
+         * By default, uses the first-strong heuristic.
+         *
+         * @param heuristic the {@code TextDirectionHeuristic} to use.
+         * @return the builder itself.
+         */
+        public Builder setTextDirectionHeuristic(TextDirectionHeuristic heuristic) {
+            this.textDirectionHeuristic = heuristic;
+            return this;
+        }
+
+        private static BidiFormatter getDefaultInstanceFromContext(boolean isRtlContext) {
+            return isRtlContext ? DEFAULT_RTL_INSTANCE : DEFAULT_LTR_INSTANCE;
+        }
+
+        /**
+         * @return A BidiFormatter with the specified options.
+         */
+        public BidiFormatter build() {
+            if (flags == DEFAULT_FLAGS &&
+                    textDirectionHeuristic == DEFAULT_TEXT_DIRECTION_HEURISTIC) {
+                return getDefaultInstanceFromContext(isRtlContext);
+            }
+            return new BidiFormatter(isRtlContext, flags, textDirectionHeuristic);
+        }
+    }
+
+    //
+    private static final int FLAG_STEREO_RESET = 2;
+    private static final int DEFAULT_FLAGS = FLAG_STEREO_RESET;
+
+    private static final BidiFormatter DEFAULT_LTR_INSTANCE = new BidiFormatter(
+            false /* LTR context */,
+            DEFAULT_FLAGS,
+            DEFAULT_TEXT_DIRECTION_HEURISTIC);
+
+    private static final BidiFormatter DEFAULT_RTL_INSTANCE = new BidiFormatter(
+            true /* RTL context */,
+            DEFAULT_FLAGS,
+            DEFAULT_TEXT_DIRECTION_HEURISTIC);
+
+    private final boolean isRtlContext;
+    private final int flags;
+    private final TextDirectionHeuristic defaultTextDirectionHeuristic;
+
+    /**
+     * Factory for creating an instance of BidiFormatter given the context directionality.
+     *
+     * @param rtlContext Whether the context directionality is RTL.
+     */
+    public static BidiFormatter getInstance(boolean rtlContext) {
+        return new Builder(rtlContext).build();
+    }
+
+    /**
+     * Factory for creating an instance of BidiFormatter given the context locale.
+     *
+     * @param locale The context locale.
+     */
+    public static BidiFormatter getInstance(Locale locale) {
+        return new Builder(locale).build();
+    }
+
+    /**
+     * @param isRtlContext Whether the context directionality is RTL or not.
+     * @param flags The option flags.
+     * @param heuristic The default text direction heuristic.
+     */
+    private BidiFormatter(boolean isRtlContext, int flags, TextDirectionHeuristic heuristic) {
+        this.isRtlContext = isRtlContext;
+        this.flags = flags;
+        this.defaultTextDirectionHeuristic = heuristic;
+    }
+
+    /**
+     * @return Whether the context directionality is RTL
+     */
+    public boolean isRtlContext() {
+        return isRtlContext;
+    }
+
+    /**
+     * @return Whether directionality "reset" should also be done before a string being
+     * bidi-wrapped, not just after it.
+     */
+    public boolean getStereoReset() {
+        return (flags & FLAG_STEREO_RESET) != 0;
+    }
+
+    /**
+     * Returns "rtl" if {@code str}'s estimated directionality is RTL, and "ltr" if it is LTR.
+     *
+     * @param str String whose directionality is to be estimated.
+     * @return "rtl" if {@code str}'s estimated directionality is RTL, and "ltr" otherwise.
+     */
+    public String dirAttrValue(String str) {
+        return dirAttrValue(isRtl(str));
+    }
+
+    /**
+     * Operates like {@link #dirAttrValue(String)}, but uses a given heuristic to estimate the
+     * {@code str}'s directionality.
+     *
+     * @param str String whose directionality is to be estimated.
+     * @param heuristic The text direction heuristic that will be used to estimate the {@code str}'s
+     *                  directionality.
+     * @return "rtl" if {@code str}'s estimated directionality is RTL, and "ltr" otherwise.
+     */
+    public String dirAttrValue(String str, TextDirectionHeuristic heuristic) {
+        return dirAttrValue(heuristic.isRtl(str, 0, str.length()));
+    }
+
+    /**
+     * Returns "rtl" if the given directionality is RTL, and "ltr" if it is LTR.
+     *
+     * @param isRtl Whether the directionality is RTL or not.
+     * @return "rtl" if the given directionality is RTL, and "ltr" otherwise.
+     */
+    public String dirAttrValue(boolean isRtl) {
+        return isRtl ? RTL_STRING : LTR_STRING;
+    }
+
+    /**
+     * Returns "dir=\"ltr\"" or "dir=\"rtl\"", depending on {@code str}'s estimated directionality,
+     * if it is not the same as the context directionality. Otherwise, returns the empty string.
+     *
+     * @param str String whose directionality is to be estimated.
+     * @return "dir=\"rtl\"" for RTL text in non-RTL context; "dir=\"ltr\"" for LTR text in non-LTR
+     *     context; else, the empty string.
+     */
+    public String dirAttr(String str) {
+        return dirAttr(isRtl(str));
+    }
+
+    /**
+     * Operates like {@link #dirAttr(String)}, but uses a given heuristic to estimate the
+     * {@code str}'s directionality.
+     *
+     * @param str String whose directionality is to be estimated.
+     * @param heuristic The text direction heuristic that will be used to estimate the {@code str}'s
+     *                  directionality.
+     * @return "dir=\"rtl\"" for RTL text in non-RTL context; "dir=\"ltr\"" for LTR text in non-LTR
+     *     context; else, the empty string.
+     */
+    public String dirAttr(String str, TextDirectionHeuristic heuristic) {
+        return dirAttr(heuristic.isRtl(str, 0, str.length()));
+    }
+
+    /**
+     * Returns "dir=\"ltr\"" or "dir=\"rtl\"", depending on the given directionality, if it is not
+     * the same as the context directionality. Otherwise, returns the empty string.
+     *
+     * @param isRtl Whether the directionality is RTL or not
+     * @return "dir=\"rtl\"" for RTL text in non-RTL context; "dir=\"ltr\"" for LTR text in non-LTR
+     *     context; else, the empty string.
+     */
+    public String dirAttr(boolean isRtl) {
+        return (isRtl != isRtlContext) ? (isRtl ? DIR_RTL_STRING :  DIR_LTR_STRING) : EMPTY_STRING;
+    }
+
+    /**
+     * Returns a Unicode bidi mark matching the context directionality (LRM or RLM) if either the
+     * overall or the exit directionality of a given string is opposite to the context directionality.
+     * Putting this after the string (including its directionality declaration wrapping) prevents it
+     * from "sticking" to other opposite-directionality text or a number appearing after it inline
+     * with only neutral content in between. Otherwise returns the empty string. While the exit
+     * directionality is determined by scanning the end of the string, the overall directionality is
+     * given explicitly in {@code dir}.
+     *
+     * @param str String after which the mark may need to appear.
+     * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+     *     else, the empty string.
+     */
+    public String markAfter(String str) {
+        return markAfter(str, defaultTextDirectionHeuristic);
+    }
+
+    /**
+     * Operates like {@link #markAfter(String)}, but uses a given heuristic to estimate the
+     * {@code str}'s directionality.
+     *
+     * @param str String after which the mark may need to appear.
+     * @param heuristic The text direction heuristic that will be used to estimate the {@code str}'s
+     *                  directionality.
+     * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+     *     else, the empty string.
+     */
+    public String markAfter(String str, TextDirectionHeuristic heuristic) {
+        final boolean isRtl = heuristic.isRtl(str, 0, str.length());
+        // getExitDir() is called only if needed (short-circuit).
+        if (!isRtlContext && (isRtl || getExitDir(str) == DIR_RTL)) {
+            return LRM_STRING;
+        }
+        if (isRtlContext && (!isRtl || getExitDir(str) == DIR_LTR)) {
+            return RLM_STRING;
+        }
+        return EMPTY_STRING;
+    }
+
+    /**
+     * Returns a Unicode bidi mark matching the context directionality (LRM or RLM) if either the
+     * overall or the entry directionality of a given string is opposite to the context
+     * directionality. Putting this before the string (including its directionality declaration
+     * wrapping) prevents it from "sticking" to other opposite-directionality text appearing before it
+     * inline with only neutral content in between. Otherwise returns the empty string. While the
+     * entry directionality is determined by scanning the beginning of the string, the overall
+     * directionality is given explicitly in {@code dir}.
+     *
+     * @param str String before which the mark may need to appear.
+     * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+     *     else, the empty string.
+     */
+    public String markBefore(String str) {
+        return markBefore(str, defaultTextDirectionHeuristic);
+    }
+
+    /**
+     * Operates like {@link #markBefore(String)}, but uses a given heuristic to estimate the
+     * {@code str}'s directionality.
+     *
+     * @param str String before which the mark may need to appear.
+     * @param heuristic The text direction heuristic that will be used to estimate the {@code str}'s
+     *                  directionality.
+     * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
+     *     else, the empty string.
+     */
+    public String markBefore(String str, TextDirectionHeuristic heuristic) {
+        final boolean isRtl = heuristic.isRtl(str, 0, str.length());
+        // getEntryDir() is called only if needed (short-circuit).
+        if (!isRtlContext && (isRtl || getEntryDir(str) == DIR_RTL)) {
+            return LRM_STRING;
+        }
+        if (isRtlContext && (!isRtl || getEntryDir(str) == DIR_LTR)) {
+            return RLM_STRING;
+        }
+        return EMPTY_STRING;
+    }
+
+    /**
+     * Returns the Unicode bidi mark matching the context directionality (LRM for LTR context
+     * directionality, RLM for RTL context directionality).
+     */
+    public String mark() {
+        return isRtlContext ? RLM_STRING : LRM_STRING;
+    }
+
+    /**
+     * Returns "right" for RTL context directionality. Otherwise for LTR context directionality
+     * returns "left".
+     */
+    public String startEdge() {
+        return isRtlContext  ? RIGHT : LEFT;
+    }
+
+    /**
+     * Returns "left" for RTL context directionality. Otherwise for LTR context directionality
+     * returns "right".
+     */
+    public String endEdge() {
+        return isRtlContext ? LEFT : RIGHT;
+    }
+
+    /**
+     * Estimates the directionality of a string using the default text direction heuristic.
+     *
+     * @param str String whose directionality is to be estimated.
+     * @return true if {@code str}'s estimated overall directionality is RTL. Otherwise returns
+     *          false.
+     */
+    public boolean isRtl(String str) {
+        return defaultTextDirectionHeuristic.isRtl(str, 0, str.length());
+    }
+
+    /**
+     * Formats a given string of unknown directionality for use in HTML output of the context
+     * directionality, so an opposite-directionality string is neither garbled nor garbles its
+     * surroundings.
+     * <p>
+     * The algorithm: estimates the directionality of the given string using the given heuristic.
+     * If the directionality is known, pass TextDirectionHeuristics.LTR or RTL for heuristic.
+     * In case its directionality doesn't match the context directionality, wraps it with a 'span'
+     * element and adds a "dir" attribute (either 'dir=\"rtl\"' or 'dir=\"ltr\"').
+     * <p>
+     * If {@code isolate}, directionally isolates the string so that it does not garble its
+     * surroundings. Currently, this is done by "resetting" the directionality after the string by
+     * appending a trailing Unicode bidi mark matching the context directionality (LRM or RLM) when
+     * either the overall directionality or the exit directionality of the string is opposite to that
+     * of the context. If the formatter was built using {@link Builder#stereoReset(boolean)} and
+     * passing "true" as an argument, also prepends a Unicode bidi mark matching the context
+     * directionality when either the overall directionality or the entry directionality of the
+     * string is opposite to that of the context.
+     * <p>
+     *
+     * @param str The input string.
+     * @param heuristic The algorithm to be used to estimate the string's overall direction.
+     * @param isolate Whether to directionally isolate the string to prevent it from garbling the
+     *     content around it.
+     * @return Input string after applying the above processing.
+     */
+    public String spanWrap(String str, TextDirectionHeuristic heuristic, boolean isolate) {
+        final boolean isRtl = heuristic.isRtl(str, 0, str.length());
+        String origStr = str;
+        str = TextUtils.htmlEncode(str);
+
+        StringBuilder result = new StringBuilder();
+        if (getStereoReset() && isolate) {
+            result.append(markBefore(origStr,
+                    isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR));
+        }
+        if (isRtl != isRtlContext) {
+            result.append("<span ").append(dirAttr(isRtl)).append('>').append(str).append("</span>");
+        } else {
+            result.append(str);
+        }
+        if (isolate) {
+            result.append(markAfter(origStr,
+                    isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR));
+        }
+        return result.toString();
+    }
+
+    /**
+     * Operates like {@link #spanWrap(String, TextDirectionHeuristic, boolean)}, but assumes
+     * {@code isolate} is true.
+     *
+     * @param str The input string.
+     * @param heuristic The algorithm to be used to estimate the string's overall direction.
+     * @return Input string after applying the above processing.
+     */
+    public String spanWrap(String str, TextDirectionHeuristic heuristic) {
+        return spanWrap(str, heuristic, true /* isolate */);
+    }
+
+    /**
+     * Operates like {@link #spanWrap(String, TextDirectionHeuristic, boolean)}, but uses the
+     * formatter's default direction estimation algorithm.
+     *
+     * @param str The input string.
+     * @param isolate Whether to directionally isolate the string to prevent it from garbling the
+     *     content around it
+     * @return Input string after applying the above processing.
+     */
+    public String spanWrap(String str, boolean isolate) {
+        return spanWrap(str, defaultTextDirectionHeuristic, isolate);
+    }
+
+    /**
+     * Operates like {@link #spanWrap(String, TextDirectionHeuristic, boolean)}, but uses the
+     * formatter's default direction estimation algorithm and assumes {@code isolate} is true.
+     *
+     * @param str The input string.
+     * @return Input string after applying the above processing.
+     */
+    public String spanWrap(String str) {
+        return spanWrap(str, defaultTextDirectionHeuristic, true /* isolate */);
+    }
+
+    /**
+     * Formats a string of given directionality for use in plain-text output of the context
+     * directionality, so an opposite-directionality string is neither garbled nor garbles its
+     * surroundings. As opposed to {@link #spanWrap}, this makes use of Unicode bidi
+     * formatting characters. In HTML, its *only* valid use is inside of elements that do not allow
+     * markup, e.g. the 'option' and 'title' elements.
+     * <p>
+     * The algorithm: In case the given directionality doesn't match the context directionality, wraps
+     * the string with Unicode bidi formatting characters: RLE+{@code str}+PDF for RTL text, or
+     * LRE+{@code str}+PDF for LTR text.
+     * <p>
+     * If {@code isolate}, directionally isolates the string so that it does not garble its
+     * surroundings. Currently, this is done by "resetting" the directionality after the string by
+     * appending a trailing Unicode bidi mark matching the context directionality (LRM or RLM) when
+     * either the overall directionality or the exit directionality of the string is opposite to that
+     * of the context. If the formatter was built using {@link Builder#stereoReset(boolean)} and
+     * passing "true" as an argument, also prepends a Unicode bidi mark matching the context
+     * directionality when either the overall directionality or the entry directionality of the
+     * string is opposite to that of the context. Note that as opposed to the overall
+     * directionality, the entry and exit directionalities are determined from the string itself.
+     * <p>
+     * Does *not* do HTML-escaping.
+     *
+     * @param str The input string.
+     * @param heuristic The algorithm to be used to estimate the string's overall direction.
+     * @param isolate Whether to directionally isolate the string to prevent it from garbling the
+     *     content around it
+     * @return Input string after applying the above processing.
+     */
+    public String unicodeWrap(String str, TextDirectionHeuristic heuristic, boolean isolate) {
+        final boolean isRtl = heuristic.isRtl(str, 0, str.length());
+        StringBuilder result = new StringBuilder();
+        if (getStereoReset() && isolate) {
+            result.append(markBefore(str,
+                    isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR));
+        }
+        if (isRtl != isRtlContext) {
+            result.append(isRtl ? RLE : LRE);
+            result.append(str);
+            result.append(PDF);
+        } else {
+            result.append(str);
+        }
+        if (isolate) {
+            result.append(markAfter(str,
+                    isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR));
+        }
+        return result.toString();
+    }
+
+    /**
+     * Operates like {@link #unicodeWrap(String, TextDirectionHeuristic, boolean)}, but assumes
+     * {@code isolate} is true.
+     *
+     * @param str The input string.
+     * @param heuristic The algorithm to be used to estimate the string's overall direction.
+     * @return Input string after applying the above processing.
+     */
+    public String unicodeWrap(String str, TextDirectionHeuristic heuristic) {
+        return unicodeWrap(str, heuristic, true /* isolate */);
+    }
+
+    /**
+     * Operates like {@link #unicodeWrap(String, TextDirectionHeuristic, boolean)}, but uses the
+     * formatter's default direction estimation algorithm.
+     *
+     * @param str The input string.
+     * @param isolate Whether to directionally isolate the string to prevent it from garbling the
+     *     content around it
+     * @return Input string after applying the above processing.
+     */
+    public String unicodeWrap(String str, boolean isolate) {
+        return unicodeWrap(str, defaultTextDirectionHeuristic, isolate);
+    }
+
+    /**
+     * Operates like {@link #unicodeWrap(String, TextDirectionHeuristic, boolean)}, but uses the
+     * formatter's default direction estimation algorithm and assumes {@code isolate} is true.
+     *
+     * @param str The input string.
+     * @return Input string after applying the above processing.
+     */
+    public String unicodeWrap(String str) {
+        return unicodeWrap(str, defaultTextDirectionHeuristic, true /* isolate */);
+    }
+
+    /**
+     * Helper method to return true if the Locale directionality is RTL.
+     *
+     * @param locale The Locale whose directionality will be checked to be RTL or LTR
+     * @return true if the {@code locale} directionality is RTL. False otherwise.
+     */
+    private static boolean isRtlLocale(Locale locale) {
+        return (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL);
+    }
+
+    /**
+     * Enum for directionality type.
+     */
+    private static final int DIR_LTR = -1;
+    private static final int DIR_UNKNOWN = 0;
+    private static final int DIR_RTL = +1;
+
+    /**
+     * Returns the directionality of the last character with strong directionality in the string, or
+     * DIR_UNKNOWN if none was encountered. For efficiency, actually scans backwards from the end of
+     * the string. Treats a non-BN character between an LRE/RLE/LRO/RLO and its matching PDF as a
+     * strong character, LTR after LRE/LRO, and RTL after RLE/RLO. The results are undefined for a
+     * string containing unbalanced LRE/RLE/LRO/RLO/PDF characters. The intended use is to check
+     * whether a logically separate item that starts with a number or a character of the string's
+     * exit directionality and follows this string inline (not counting any neutral characters in
+     * between) would "stick" to it in an opposite-directionality context, thus being displayed in
+     * an incorrect position. An LRM or RLM character (the one of the context's directionality)
+     * between the two will prevent such sticking.
+     *
+     * @param str the string to check.
+     */
+    private static int getExitDir(String str) {
+        return new DirectionalityEstimator(str, false /* isHtml */).getExitDir();
+    }
+
+    /**
+     * Returns the directionality of the first character with strong directionality in the string,
+     * or DIR_UNKNOWN if none was encountered. Treats a non-BN character between an
+     * LRE/RLE/LRO/RLO and its matching PDF as a strong character, LTR after LRE/LRO, and RTL after
+     * RLE/RLO. The results are undefined for a string containing unbalanced LRE/RLE/LRO/RLO/PDF
+     * characters. The intended use is to check whether a logically separate item that ends with a
+     * character of the string's entry directionality and precedes the string inline (not counting
+     * any neutral characters in between) would "stick" to it in an opposite-directionality context,
+     * thus being displayed in an incorrect position. An LRM or RLM character (the one of the
+     * context's directionality) between the two will prevent such sticking.
+     *
+     * @param str the string to check.
+     */
+    private static int getEntryDir(String str) {
+        return new DirectionalityEstimator(str, false /* isHtml */).getEntryDir();
+    }
+
+    /**
+     * An object that estimates the directionality of a given string by various methods.
+     *
+     */
+    private static class DirectionalityEstimator {
+
+        // Internal static variables and constants.
+
+        /**
+         * Size of the bidi character class cache. The results of the Character.getDirectionality()
+         * calls on the lowest DIR_TYPE_CACHE_SIZE codepoints are kept in an array for speed.
+         * The 0x700 value is designed to leave all the European and Near Eastern languages in the
+         * cache. It can be reduced to 0x180, restricting the cache to the Western European
+         * languages.
+         */
+        private static final int DIR_TYPE_CACHE_SIZE = 0x700;
+
+        /**
+         * The bidi character class cache.
+         */
+        private static final byte DIR_TYPE_CACHE[];
+
+        static {
+            DIR_TYPE_CACHE = new byte[DIR_TYPE_CACHE_SIZE];
+            for (int i = 0; i < DIR_TYPE_CACHE_SIZE; i++) {
+                DIR_TYPE_CACHE[i] = Character.getDirectionality(i);
+            }
+        }
+
+        // Internal instance variables.
+
+        /**
+         * The text to be scanned.
+         */
+        private final String text;
+
+        /**
+         * Whether the text to be scanned is to be treated as HTML, i.e. skipping over tags and
+         * entities when looking for the next / preceding dir type.
+         */
+        private final boolean isHtml;
+
+        /**
+         * The length of the text in chars.
+         */
+        private final int length;
+
+        /**
+         * The current position in the text.
+         */
+        private int charIndex;
+
+        /**
+         * The char encountered by the last dirTypeForward or dirTypeBackward call. If it
+         * encountered a supplementary codepoint, this contains a char that is not a valid
+         * codepoint. This is ok, because this member is only used to detect some well-known ASCII
+         * syntax, e.g. "http://" and the beginning of an HTML tag or entity.
+         */
+        private char lastChar;
+
+        /**
+         * Constructor.
+         *
+         * @param text The string to scan.
+         * @param isHtml Whether the text to be scanned is to be treated as HTML, i.e. skipping over
+         *     tags and entities.
+         */
+        DirectionalityEstimator(String text, boolean isHtml) {
+            this.text = text;
+            this.isHtml = isHtml;
+            length = text.length();
+        }
+
+        /**
+         * Returns the directionality of the first character with strong directionality in the
+         * string, or DIR_UNKNOWN if none was encountered. Treats a non-BN character between an
+         * LRE/RLE/LRO/RLO and its matching PDF as a strong character, LTR after LRE/LRO, and RTL
+         * after RLE/RLO. The results are undefined for a string containing unbalanced
+         * LRE/RLE/LRO/RLO/PDF characters.
+         */
+        int getEntryDir() {
+            // The reason for this method name, as opposed to getFirstStrongDir(), is that
+            // "first strong" is a commonly used description of Unicode's estimation algorithm,
+            // but the two must treat formatting characters quite differently. Thus, we are staying
+            // away from both "first" and "last" in these method names to avoid confusion.
+            charIndex = 0;
+            int embeddingLevel = 0;
+            int embeddingLevelDir = DIR_UNKNOWN;
+            int firstNonEmptyEmbeddingLevel = 0;
+            while (charIndex < length && firstNonEmptyEmbeddingLevel == 0) {
+                switch (dirTypeForward()) {
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+                        ++embeddingLevel;
+                        embeddingLevelDir = DIR_LTR;
+                        break;
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+                        ++embeddingLevel;
+                        embeddingLevelDir = DIR_RTL;
+                        break;
+                    case Character.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT:
+                        --embeddingLevel;
+                        // To restore embeddingLevelDir to its previous value, we would need a
+                        // stack, which we want to avoid. Thus, at this point we do not know the
+                        // current embedding's directionality.
+                        embeddingLevelDir = DIR_UNKNOWN;
+                        break;
+                    case Character.DIRECTIONALITY_BOUNDARY_NEUTRAL:
+                        break;
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+                        if (embeddingLevel == 0) {
+                            return DIR_LTR;
+                        }
+                        firstNonEmptyEmbeddingLevel = embeddingLevel;
+                        break;
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+                        if (embeddingLevel == 0) {
+                            return DIR_RTL;
+                        }
+                        firstNonEmptyEmbeddingLevel = embeddingLevel;
+                        break;
+                    default:
+                        firstNonEmptyEmbeddingLevel = embeddingLevel;
+                        break;
+                }
+            }
+
+            // We have either found a non-empty embedding or scanned the entire string finding
+            // neither a non-empty embedding nor a strong character outside of an embedding.
+            if (firstNonEmptyEmbeddingLevel == 0) {
+                // We have not found a non-empty embedding. Thus, the string contains neither a
+                // non-empty embedding nor a strong character outside of an embedding.
+                return DIR_UNKNOWN;
+            }
+
+            // We have found a non-empty embedding.
+            if (embeddingLevelDir != DIR_UNKNOWN) {
+                // We know the directionality of the non-empty embedding.
+                return embeddingLevelDir;
+            }
+
+            // We do not remember the directionality of the non-empty embedding we found. So, we go
+            // backwards to find the start of the non-empty embedding and get its directionality.
+            while (charIndex > 0) {
+                switch (dirTypeBackward()) {
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+                        if (firstNonEmptyEmbeddingLevel == embeddingLevel) {
+                            return DIR_LTR;
+                        }
+                        --embeddingLevel;
+                        break;
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+                        if (firstNonEmptyEmbeddingLevel == embeddingLevel) {
+                            return DIR_RTL;
+                        }
+                        --embeddingLevel;
+                        break;
+                    case Character.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT:
+                        ++embeddingLevel;
+                        break;
+                }
+            }
+            // We should never get here.
+            return DIR_UNKNOWN;
+        }
+
+        /**
+         * Returns the directionality of the last character with strong directionality in the
+         * string, or DIR_UNKNOWN if none was encountered. For efficiency, actually scans backwards
+         * from the end of the string. Treats a non-BN character between an LRE/RLE/LRO/RLO and its
+         * matching PDF as a strong character, LTR after LRE/LRO, and RTL after RLE/RLO. The results
+         * are undefined for a string containing unbalanced LRE/RLE/LRO/RLO/PDF characters.
+         */
+        int getExitDir() {
+            // The reason for this method name, as opposed to getLastStrongDir(), is that "last
+            // strong" sounds like the exact opposite of "first strong", which is a commonly used
+            // description of Unicode's estimation algorithm (getUnicodeDir() above), but the two
+            // must treat formatting characters quite differently. Thus, we are staying away from
+            // both "first" and "last" in these method names to avoid confusion.
+            charIndex = length;
+            int embeddingLevel = 0;
+            int lastNonEmptyEmbeddingLevel = 0;
+            while (charIndex > 0) {
+                switch (dirTypeBackward()) {
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+                        if (embeddingLevel == 0) {
+                            return DIR_LTR;
+                        }
+                        if (lastNonEmptyEmbeddingLevel == 0) {
+                            lastNonEmptyEmbeddingLevel = embeddingLevel;
+                        }
+                        break;
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
+                    case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
+                        if (lastNonEmptyEmbeddingLevel == embeddingLevel) {
+                            return DIR_LTR;
+                        }
+                        --embeddingLevel;
+                        break;
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+                        if (embeddingLevel == 0) {
+                            return DIR_RTL;
+                        }
+                        if (lastNonEmptyEmbeddingLevel == 0) {
+                            lastNonEmptyEmbeddingLevel = embeddingLevel;
+                        }
+                        break;
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
+                    case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+                        if (lastNonEmptyEmbeddingLevel == embeddingLevel) {
+                            return DIR_RTL;
+                        }
+                        --embeddingLevel;
+                        break;
+                    case Character.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT:
+                        ++embeddingLevel;
+                        break;
+                    case Character.DIRECTIONALITY_BOUNDARY_NEUTRAL:
+                        break;
+                    default:
+                        if (lastNonEmptyEmbeddingLevel == 0) {
+                            lastNonEmptyEmbeddingLevel = embeddingLevel;
+                        }
+                        break;
+                }
+            }
+            return DIR_UNKNOWN;
+        }
+
+        // Internal methods
+
+        /**
+         * Gets the bidi character class, i.e. Character.getDirectionality(), of a given char, using
+         * a cache for speed. Not designed for supplementary codepoints, whose results we do not
+         * cache.
+         */
+        private static byte getCachedDirectionality(char c) {
+            return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : Character.getDirectionality(c);
+        }
+
+        /**
+         * Returns the Character.DIRECTIONALITY_... value of the next codepoint and advances
+         * charIndex. If isHtml, and the codepoint is '<' or '&', advances through the tag/entity,
+         * and returns Character.DIRECTIONALITY_WHITESPACE. For an entity, it would be best to
+         * figure out the actual character, and return its dirtype, but treating it as whitespace is
+         * good enough for our purposes.
+         *
+         * @throws java.lang.IndexOutOfBoundsException if called when charIndex >= length or < 0.
+         */
+        byte dirTypeForward() {
+            lastChar = text.charAt(charIndex);
+            if (Character.isHighSurrogate(lastChar)) {
+                int codePoint = Character.codePointAt(text, charIndex);
+                charIndex += Character.charCount(codePoint);
+                return Character.getDirectionality(codePoint);
+            }
+            charIndex++;
+            byte dirType = getCachedDirectionality(lastChar);
+            if (isHtml) {
+                // Process tags and entities.
+                if (lastChar == '<') {
+                    dirType = skipTagForward();
+                } else if (lastChar == '&') {
+                    dirType = skipEntityForward();
+                }
+            }
+            return dirType;
+        }
+
+        /**
+         * Returns the Character.DIRECTIONALITY_... value of the preceding codepoint and advances
+         * charIndex backwards. If isHtml, and the codepoint is the end of a complete HTML tag or
+         * entity, advances over the whole tag/entity and returns
+         * Character.DIRECTIONALITY_WHITESPACE. For an entity, it would be best to figure out the
+         * actual character, and return its dirtype, but treating it as whitespace is good enough
+         * for our purposes.
+         *
+         * @throws java.lang.IndexOutOfBoundsException if called when charIndex > length or <= 0.
+         */
+        byte dirTypeBackward() {
+            lastChar = text.charAt(charIndex - 1);
+            if (Character.isLowSurrogate(lastChar)) {
+                int codePoint = Character.codePointBefore(text, charIndex);
+                charIndex -= Character.charCount(codePoint);
+                return Character.getDirectionality(codePoint);
+            }
+            charIndex--;
+            byte dirType = getCachedDirectionality(lastChar);
+            if (isHtml) {
+                // Process tags and entities.
+                if (lastChar == '>') {
+                    dirType = skipTagBackward();
+                } else if (lastChar == ';') {
+                    dirType = skipEntityBackward();
+                }
+            }
+            return dirType;
+        }
+
+        /**
+         * Advances charIndex forward through an HTML tag (after the opening &lt; has already been
+         * read) and returns Character.DIRECTIONALITY_WHITESPACE. If there is no matching &gt;,
+         * does not change charIndex and returns Character.DIRECTIONALITY_OTHER_NEUTRALS (for the
+         * &lt; that hadn't been part of a tag after all).
+         */
+        private byte skipTagForward() {
+            int initialCharIndex = charIndex;
+            while (charIndex < length) {
+                lastChar = text.charAt(charIndex++);
+                if (lastChar == '>') {
+                    // The end of the tag.
+                    return Character.DIRECTIONALITY_WHITESPACE;
+                }
+                if (lastChar == '"' || lastChar == '\'') {
+                    // Skip over a quoted attribute value inside the tag.
+                    char quote = lastChar;
+                    while (charIndex < length && (lastChar = text.charAt(charIndex++)) != quote) {}
+                }
+            }
+            // The original '<' wasn't the start of a tag after all.
+            charIndex = initialCharIndex;
+            lastChar = '<';
+            return Character.DIRECTIONALITY_OTHER_NEUTRALS;
+        }
+
+        /**
+         * Advances charIndex backward through an HTML tag (after the closing &gt; has already been
+         * read) and returns Character.DIRECTIONALITY_WHITESPACE. If there is no matching &lt;, does
+         * not change charIndex and returns Character.DIRECTIONALITY_OTHER_NEUTRALS (for the &gt;
+         * that hadn't been part of a tag after all). Nevertheless, the running time for calling
+         * skipTagBackward() in a loop remains linear in the size of the text, even for a text like
+         * "&gt;&gt;&gt;&gt;", because skipTagBackward() also stops looking for a matching &lt;
+         * when it encounters another &gt;.
+         */
+        private byte skipTagBackward() {
+            int initialCharIndex = charIndex;
+            while (charIndex > 0) {
+                lastChar = text.charAt(--charIndex);
+                if (lastChar == '<') {
+                    // The start of the tag.
+                    return Character.DIRECTIONALITY_WHITESPACE;
+                }
+                if (lastChar == '>') {
+                    break;
+                }
+                if (lastChar == '"' || lastChar == '\'') {
+                    // Skip over a quoted attribute value inside the tag.
+                    char quote = lastChar;
+                    while (charIndex > 0 && (lastChar = text.charAt(--charIndex)) != quote) {}
+                }
+            }
+            // The original '>' wasn't the end of a tag after all.
+            charIndex = initialCharIndex;
+            lastChar = '>';
+            return Character.DIRECTIONALITY_OTHER_NEUTRALS;
+        }
+
+        /**
+         * Advances charIndex forward through an HTML character entity tag (after the opening
+         * &amp; has already been read) and returns Character.DIRECTIONALITY_WHITESPACE. It would be
+         * best to figure out the actual character and return its dirtype, but this is good enough.
+         */
+        private byte skipEntityForward() {
+            while (charIndex < length && (lastChar = text.charAt(charIndex++)) != ';') {}
+            return Character.DIRECTIONALITY_WHITESPACE;
+        }
+
+        /**
+         * Advances charIndex backward through an HTML character entity tag (after the closing ;
+         * has already been read) and returns Character.DIRECTIONALITY_WHITESPACE. It would be best
+         * to figure out the actual character and return its dirtype, but this is good enough.
+         * If there is no matching &amp;, does not change charIndex and returns
+         * Character.DIRECTIONALITY_OTHER_NEUTRALS (for the ';' that did not start an entity after
+         * all). Nevertheless, the running time for calling skipEntityBackward() in a loop remains
+         * linear in the size of the text, even for a text like ";;;;;;;", because skipTagBackward()
+         * also stops looking for a matching &amp; when it encounters another ;.
+         */
+        private byte skipEntityBackward() {
+            int initialCharIndex = charIndex;
+            while (charIndex > 0) {
+                lastChar = text.charAt(--charIndex);
+                if (lastChar == '&') {
+                    return Character.DIRECTIONALITY_WHITESPACE;
+                }
+                if (lastChar == ';') {
+                    break;
+                }
+            }
+            charIndex = initialCharIndex;
+            lastChar = ';';
+            return Character.DIRECTIONALITY_OTHER_NEUTRALS;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index e856501..dae47b8 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -74,6 +74,15 @@
     public static final int DENSITY_XXHIGH = 480;
 
     /**
+     * Standard quantized DPI for extra-extra-extra-high-density screens.  Applications
+     * should not generally worry about this density; relying on XHIGH graphics
+     * being scaled up to it should be sufficient for almost all cases.  A typical
+     * use of this density would be 4K television screens -- 3840x2160, which
+     * is 2x a traditional HD 1920x1080 screen which runs at DENSITY_XHIGH.
+     */
+    public static final int DENSITY_XXXHIGH = 640;
+
+    /**
      * The reference density used throughout the system.
      */
     public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 85ed8db..12cce8b 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -1235,6 +1235,7 @@
             Assoc<Spec, Bounds> assoc = Assoc.of(Spec.class, Bounds.class);
             for (int i = 0, N = getChildCount(); i < N; i++) {
                 View c = getChildAt(i);
+                if (c.getVisibility() == View.GONE) continue;
                 LayoutParams lp = getLayoutParams(c);
                 Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
                 Bounds bounds = getAlignment(spec.alignment, horizontal).getBounds();
@@ -1250,6 +1251,7 @@
             }
             for (int i = 0, N = getChildCount(); i < N; i++) {
                 View c = getChildAt(i);
+                if (c.getVisibility() == View.GONE) continue;
                 LayoutParams lp = getLayoutParams(c);
                 Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
                 groupBounds.getValue(i).include(GridLayout.this, c, spec, this);
diff --git a/core/java/com/android/internal/app/IAppOpsCallback.aidl b/core/java/com/android/internal/app/IAppOpsCallback.aidl
index 4e75a61..afbc609 100644
--- a/core/java/com/android/internal/app/IAppOpsCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsCallback.aidl
@@ -16,6 +16,8 @@
 
 package com.android.internal.app;
 
+// This interface is also used by native code, so must
+// be kept in sync with frameworks/native/include/binder/IAppOpsCallback.h
 oneway interface IAppOpsCallback {
     void opChanged(int op, String packageName);
 }
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 83967f6..a9da863 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -20,13 +20,17 @@
 import com.android.internal.app.IAppOpsCallback;
 
 interface IAppOpsService {
-    List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
-    List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
-    void setMode(int code, int uid, String packageName, int mode);
+    // These first methods are also called by native code, so must
+    // be kept in sync with frameworks/native/include/binder/IAppOpsService.h
     int checkOperation(int code, int uid, String packageName);
     int noteOperation(int code, int uid, String packageName);
     int startOperation(int code, int uid, String packageName);
     void finishOperation(int code, int uid, String packageName);
     void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
     void stopWatchingMode(IAppOpsCallback callback);
+
+    // Remaining methods are only used in Java.
+    List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
+    List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
+    void setMode(int code, int uid, String packageName, int mode);
 }
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 6641f2c..28fd05f 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -820,7 +820,7 @@
              * and we won't log special messages SM_INIT_CMD or SM_QUIT_CMD which
              * always set msg.obj to the handler.
              */
-            boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj == mSmHandlerObj);
+            boolean recordLogMsg = mSm.recordLogRec(mMsg) && (msg.obj != mSmHandlerObj);
 
             if (mLogRecords.logOnlyTransitions()) {
                 /** Record only if there is a transition */
diff --git a/core/res/Android.mk b/core/res/Android.mk
index 22f4fdc..cfc791d 100644
--- a/core/res/Android.mk
+++ b/core/res/Android.mk
@@ -42,7 +42,3 @@
 
 # Make sure the system .rs files get compiled before building the package-export.apk.
 # $(resource_export_package): $(framework_RenderScript_STAMP_FILE)
-
-# define a global intermediate target that other module may depend on.
-.PHONY: framework-res-package-target
-framework-res-package-target: $(LOCAL_BUILT_MODULE)
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 960232a..c1cb9d59 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Дазваляе прыкладаннм кіраваць сеткавымі палітыкамі і вызначаць правілы пэўных прыкладанняў."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"змяніць улік выкарыстання сеткі"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дазваляе прыкладанням змяняць метад уліку выкарыстання сеткі прыкладаннямі. Не для выкарыстання звычайнымі прыкладаннямі."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"доступ да паведамленняў"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дазваляе прыкладанню атрымлiваць, правяраць i выдаляць апавяшчэннi, у тым лiку апублiкаваныя iншымi прыкладаннямi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устанавіць правілы паролю"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Кіраванне даўжынёй і колькасцю знакаў у паролі разблакоўкі экрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Сачыць за спробамі разблакоўкі экрана"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 7f351da..158134e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Разрешава на приложението да управлява правилата на мрежата и да определя такива за конкретно приложение."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"промяна на отчетността на употребата на мрежа"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Разрешава на приложението да променя това как употребата на мрежа се отчита спрямо приложенията. Не е предназначено за нормални приложения."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"достъп до известията"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Разрешава на приложението да извлича, преглежда и изчиства известия, включително публикуваните от други приложения."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролирайте дължината и разрешените знаци за паролите за отключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index de1f9aa..e3ee35d 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permet que l\'aplicació gestioni les polítiques de la xarxa i que defineixi les regles específiques d\'aplicació."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificació del càlcul d\'ús de la xarxa"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet que l\'aplicació modifiqui la manera com es calcula l\'ús de la xarxa per part de les aplicacions. No indicat per a les aplicacions normals."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"accedeix a les notificacions"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control d\'intents de desbloqueig de pantalla"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0b1715e..35798a4 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Umožňuje aplikaci spravovat zásady sítě a definovat pravidla pro konkrétní aplikace."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"upravit kontrolu používání sítě"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Umožňuje aplikaci upravit způsob výpočtu využití sítě aplikacemi. Toto oprávnění není určeno pro běžné aplikace."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"přístup k oznámením"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikacím načítat, zobrazovat a mazat oznámení včetně těch přidaných jinými aplikacemi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Řídit délku hesel pro odemčení obrazovky a povolené znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 860a9be..477f313 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Tillader, at appen kan administrere netværkspolitikker og definere appspecifikke regler."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"skift afregning af netværksbrug"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Tillader, at appen kan ændre den måde, som netværksforbrug udregnes på i forhold til apps. Anvendes ikke af normale apps."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"adgang til underretninger"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillader, at appen kan hente, undersøge og rydde underretninger, herunder dem, der er sendt af andre apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 3a8c6ab..770cc61 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ermöglicht der App, Netzwerkrichtlinien zu verwalten und anwendungsspezifische Regeln festzulegen"</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Zuordnung für Netzwerknutzung ändern"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ermöglicht der App, die Art und Weise zu ändern, wie der Netzwerkverbrauch im Hinblick auf Apps berechnet wird. Nicht für normale Apps vorgesehen."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"Auf Benachrichtigungen zugreifen"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Bildschirms festlegen"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9f7399b..40fc411 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Επιτρέπει στην εφαρμογή τη διαχείριση των πολιτικών δικτύου και τον ορισμό κανόνων για ορισμένες εφαρμογές."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"τροποποίηση υπολογισμού χρήσης δικτύου"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Επιτρέπει στην εφαρμογή την τροποποίηση του τρόπου υπολογισμού της χρήσης δικτύου έναντι των εφαρμογών. Δεν προορίζεται για χρήση από συνήθεις εφαρμογές."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"πρόσβαση στις ειδοποιήσεις"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Επιτρέπει στην εφαρμογή να ανακτά, να εξετάζει και να απαλείφει ειδοποιήσεις, συμπεριλαμβανομένων εκείνων που δημοσιεύονται από άλλες εφαρμογές."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index ec2a60e..4af1886 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Allows the app to manage network policies and define app-specific rules."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modify network usage accounting"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Allows the app to modify how network usage is accounted against apps. Not for use by normal apps."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"access notifications"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index c6be92d..8517662 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que la aplicación administre las políticas de red y defina reglas específicas de la aplicación."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Modificar la administración del uso de redes"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que la aplicación modifique cómo se registra el uso de red en relación con las aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"acceder a las notificaciones"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y elimine notificaciones, incluidas aquellas publicadas por otras aplicaciones."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 6c0761c..2b657c8 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que la aplicación administre políticas de red y defina reglas específicas de la aplicación."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar cálculo de uso de red"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que la aplicación modifique cómo se registra el uso de red en relación con las aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"acceder a las notificaciones"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y borre notificaciones, incluidas las que han publicado otras aplicaciones."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 26482bd..3303f00 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Võimaldab rakendusel hallata võrgueeskirju ja määratleda rakendusespetsiifilisi reegleid."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"võrgukasutuse arvestamise muutmine"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Võimaldab rakendusel muuta võrgukasutuse loendamist rakenduste suhtes. Mitte kasutada tavarakenduste puhul."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"juurdepääsu märguanded"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Võimaldab rakendusel tuua, kontrollida ja kustutada märguandeid, sh neid, mille on postitanud teised rakendused."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrollige ekraaniluku avamise paroolide pikkust ja tähemärke."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5e8ac2b..b4a15c5 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"به برنامه اجازه می‎دهد تا خط مشی‎های شبکه را مدیریت کند و قوانین خاص برنامه را تعیین کند."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"اصلاح محاسبه استفاده از شبکه"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"به برنامه اجازه می‎دهد تا نحوه محاسبه کاربرد شبکه در برنامه را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"اعلان‌های دسترسی"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"به برنامه اجازه می‌دهد به بازیابی، بررسی و پاک کردن اعلان‌ها از جمله موارد پست شده توسط سایر برنامه‌ها بپردازد."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسه‎های مجاز در گذرواژه‌های بازکردن قفل صفحه را کنترل کنید."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 43cd8ab..45f4a05 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Sallii sovelluksen hallinnoida verkkokäytäntöjä ja määritellä sovelluskohtaisia sääntöjä."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verkon käytön seurannan muokkaaminen"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Antaa sovelluksen muokata, miten sovellusten verkonkäyttöä lasketaan. Ei tavallisten sovellusten käyttöön."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"käytä ilmoituksia"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Antaa sovelluksen noutaa, tutkia ja tyhjentää ilmoituksia (myös muiden sovelluksien lähettämiä)."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index b5d2d2b..c94946e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permet à l\'application de gérer les stratégies du réseau et de définir celles qui sont spécifiques à l\'application."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifier le système de comptabilisation de l\'utilisation du réseau"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet à l\'application de modifier l\'utilisation du réseau par les autres applications. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"accéder aux notifications"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8175fa4..3521f4b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"एप्‍लिकेशन को नेटवर्क नीतियां प्रबंधित करने और एप्‍लिकेशन-विशिष्‍ट नियमों को परिभाषित करने देता है."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"एप्लिकेशन को यह संशोधित करने देता है कि एप्‍लिकेशन की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्‍य एप्‍लिकेशन द्वारा उपयोग करने के लिए नहीं."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"सूचनाओं तक पहुंचें"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"एप्लिकेशन को सूचनाओं को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य एप्लिकेशन के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"स्‍क्रीन-अनलॉक पासवर्ड में अनुमति प्राप्त लंबाई और वर्णों को नियंत्रित करें."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"स्‍क्रीन-अनलॉक के प्रयासों पर निगरानी रखें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4773c941..ce7e954 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Aplikaciji omogućuje upravljanje mrežnim pravilima i određivanje pravila za aplikacije."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"izmjena evidencije mrežne upotrebe"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Omogućuje aplikaciji izmjenu načina upotrebe mreže u odnosu na aplikacije. Nije namijenjeno uobičajenim aplikacijama."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"pristup obavijestima"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Omogućuje aplikaciji dohvaćanje, pregledavanje i brisanje obavijesti, uključujući obavijesti drugih aplikacija."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index a6ea0f6..a472123 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Lehetővé teszi az alkalmazás számára, hogy kezelje a hálózati irányelveket és meghatározza az alkalmazásspecifikus szabályokat."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"hálózathasználat elszámolásának módosítása"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lehetővé teszi az alkalmazás számára annak módosítását, hogy a hálózathasználatot hogyan számolják el az alkalmazások esetében. Normál alkalmazások nem használhatják."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"hozzáférési értesítések"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lehetővé teszi, hogy az alkalmazás értesítéseket kérdezzen le, vizsgáljon és tisztítson meg, beleértve az egyéb alkalmazások által közzétett értesítéseket is."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 72199a1..d0b4d61 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Mengizinkan apl mengelola kebijakan jaringan dan menentukan peraturan khusus apl."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"mengubah penghitungan penggunaan jaringan"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Mengizinkan apl memodifikasi cara penggunaan jaringan diperhitungkan terhadap apl. Tidak untuk digunakan oleh apl normal."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"mengakses pemberitahuan"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposkan oleh aplikasi lain."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrol panjang dan karakter yang diizinkan dalam sandi pembuka layar."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1c95e73..87d21fe 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Consente all\'applicazione di gestire le norme di rete e definire le regole specifiche delle applicazioni."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifica calcolo dell\'utilizzo della rete"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Consente all\'applicazione di modificare il calcolo dell\'utilizzo della rete tra le applicazioni. Da non usare per normali applicazioni."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"accesso a notifiche"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Consente all\'app di recuperare, esaminare e cancellare notifiche, comprese quelle pubblicate da altre app."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 333aaa9..1dfdf97 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"앱이 네트워크 정책을 관리하고 앱별 규칙을 정의할 수 있도록 허용합니다."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"네트워크 사용량 계산 수정"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"애플리케이션이 애플리케이션의 네트워크 사용량을 계산하는 방식을 수정할 수 있도록 허용합니다. 일반 애플리케이션에서는 사용하지 않습니다."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"액세스 알림"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"앱이 다른 앱에서 게시한 알림을 비롯하여 알림을 검색하고 살펴보며 삭제할 수 있도록 허용합니다."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a3460d16..3b6e440 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Leidžiama programai valdyti tinklo politiką ir apibrėžti konkrečios programos taisykles."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"keisti tinklo naudojimo apskaitą"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Leidžiama programai keisti, kaip tinklas naudojamas, palyginti su programomis. Neskirta naudoti įprastoms programoms."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"pasiekti pranešimus"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Programai leidžiama gauti, patikrinti ir išvalyti pranešimus, įskaitant pranešimus, kuriuos paskelbė kitos programos."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir leidžiamus naudoti simbolius."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e92fa7d..646b7fa 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ļauj lietotnei pārvaldīt tīkla politikas un noteikt lietotnes kārtulas."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Tīkla lietojuma uzskaites mainīšana"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ļauj lietotnei mainīt to, kā tīkla lietojums tiek uzskaitīts saistībā ar lietotnēm. Atļauja neattiecas uz parastām lietotnēm."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"piekļuve paziņojumiem"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ļauj lietotnei izgūt, pārbaudīt un dzēst paziņojumus, tostarp lietotņu publicētos paziņojumus."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 0f30f40..784a424 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Membenarkan apl mengurus dasar rangkaian dan menentukan peraturan khusus apl."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ubah suai perakaunan penggunaan rangkaian"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Membenarkan apl untuk mengubah suai bagaimana penggunaan rangkaian diambil kira terhadap apl. Bukan untuk digunakan oleh apl biasa."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"pemberitahuan akses"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Membenarkan apl untuk mendapatkan semula, memeriksa dan memadam bersih pemberitahuan, termasuk yang disiarkan oleh apl lain."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 1cb41c4..485a11f8 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Lar appen administrere retningslinjene for nettverket og definere appspesifikke regler."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Modifisering av regnskapsføring av nettverksbruk"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lar appen endre hvordan nettverksbruk regnes ut for apper. Ikke beregnet på vanlige apper."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"varseltilgang"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lar appen hente, gjennomgå og fjerne varsler, inkludert de som sendes fra andre apper."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 757a813..95da93b 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Hiermee kan de app het netwerkbeleid beheren en app-specifieke regels definiëren."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verrekening van netwerkgebruik aanpassen"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Hiermee kan een app aanpassen hoe het netwerkgebruik wordt toegekend aan apps. Dit wordt niet gebruikt door normale apps."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"toegang tot meldingen"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Hiermee kan de app meldingen ophalen, onderzoeken en wissen, waaronder meldingen die zijn verzonden door andere apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a5405de..f15c106 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Pozwala aplikacji na zarządzanie zasadami dotyczącymi sieci i definiowanie reguł aplikacji."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modyfikowanie sposobu naliczania użycia sieci"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Pozwala aplikacji na zmienianie sposobu rozliczania wykorzystania sieci przez aplikacje. Nieprzeznaczone dla zwykłych aplikacji."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"dostęp do powiadomień"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umożliwia aplikacji pobieranie, sprawdzanie i usuwanie powiadomień, także tych, które pochodzą z innych aplikacji."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 28b6f9d..186eb3e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que a aplicação faça a gestão de políticas de rede e defina regras específicas de aplicações."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar contabilização da utilização da rede"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que a aplicação modifique o modo como a utilização da rede é contabilizada em relação a aplicações. Nunca é necessário para aplicações normais."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"aceder às notificações"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que a aplicação obtenha, examine e limpe notificações, incluindo as que foram publicadas por outras aplicações."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index bcec57e..a2c6675 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que o aplicativo gerencie políticas de rede e definia regras específicas para o aplicativo."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar contagem de uso da rede"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que o aplicativo modifique como o uso da rede é contabilizado em relação aos aplicativos. Não deve ser usado em aplicativos normais."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"acessar notificações"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que o aplicativo recupere, examine e limpe notificações, inclusive as postadas por outros aplicativos."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controle o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 52fee9b..e6d142b 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite aplicaţiei să gestioneze politicile de reţea şi să definească regulile specifice aplicaţiilor."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificaţi modul de calcul al utilizării reţelei"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicaţiei să modifice modul în care este calculată utilizarea reţelei pentru aplicaţii. Nu se utilizează de aplicaţiile obişnuite."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"accesare notificări"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 741d78f..fa623e0 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Приложение сможет управлять сетевыми политиками и определять правила для отдельных приложений."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"изменение учета использования сети"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Приложение сможет изменять порядок расчета использования сетевых ресурсов различными программами. Это разрешение не используется обычными приложениями."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"доступ к уведомлениям"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Приложение сможет получать, проверять и удалять уведомления, включая те, что опубликованы другими приложениями."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e0126da..5f49e68 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Umožňuje aplikácii spravovať pravidlá siete a definovať pravidlá pre konkrétnu aplikáciu."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"zmeniť kontrolu používania siete"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Umožňuje aplikácii upraviť používanie siete jednotlivými aplikáciami. Bežné aplikácie toto nastavenie nepoužívajú."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"prístup k upozorneniam"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikácii načítať, zobrazovať a mazať upozornenia vrátane tých, ktoré boli uverejnené inými aplikáciami."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Ovládanie dĺžky hesiel na odomknutie obrazovky a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 73d308c..aa240de 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Programu omogoča upravljanje pravilnikov o omrežju in določanje pravil za program."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"spremeni obračunavanje uporabe omrežja"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Programu omogoča, da spremeni uporabo omrežja na podlagi programov. Ni za uporabo z navadnimi programi."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"dostop do obvestil"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Dovoli aplikaciji, da prenese, razišče in izbriše obvestila, tudi tista, ki so jih objavile druge aplikacije."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 127d5eb..7a3ff07 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Дозвољава апликацији да управља смерницама за мрежу и одређује посебна правила за апликацију."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"измените обрачунавање коришћења мреже"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дозвољава апликацији да измени начин на који апликације користе мрежу. Не користе је уобичајене апликације."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"приступ обавештењима"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозвољава апликацији да преузима, испитује и брише обавештења, укључујући она која постављају друге апликације."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролишите дужину и знакове дозвољене у лозинкама за откључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index aab6047..eca52e6 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Tillåter att appen hanterar nätverkspolicyer och definierar appspecifika regler."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ändra nätverksredovisningen"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Tillåter att appen ändrar hur nätverksanvändning redovisas för appar. Används inte av vanliga appar."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"få åtkomst till meddelanden"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillåter att appen hämtar, granskar och raderar meddelanden, även sådana som skickats av andra appar."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 109566f..d0b1510 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Inaruhusu programu kudhibiti sera za mtandao na kufafanua sheria maalum za programu."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"badilisha uthibitishaji wa matumizi ya mtandao"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Huruhusu programu kurekebisha jinsi matumizi ya mtandao yana hesabika dhidi ya programu. Sio ya matumizi na programu za kawaida."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"fikia arifa"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Dhibiti urefu na vibambo vinavyoruhusiwa katika manenosiri ya kufungua skrini."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index e7d4b4f..e7df782 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"อนุญาตให้แอปพลิเคชันจัดการนโยบายเครือข่ายและกำหนดกฎเฉพาะแอปพลิเคชัน"</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"แก้ไขการบันทึกบัญชีการใช้งานเครือข่าย"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"อนุญาตให้แอปพลิเคชันแก้ไขวิธีการบันทึกบัญชีการใช้งานเครือข่ายของแอปพลิเคชัน ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"เข้าถึงการแจ้งเตือน"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกคืน ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 0021828..6268786 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Pinapayagan ang app na pamahalaan ang mga patakaran ng network at ilarawan ang mga patakarang tukoy sa app."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"baguhin ang pagkukuwenta sa paggamit ng network"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Pinapayagan ang app na baguhin kung paano isinasaalang-alang ang paggamit ng network laban sa apps. Hindi para sa paggamit ng normal na apps."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"i-access ang mga notification"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Pinapayagan ang app na kumuha, sumuri, at mag-clear ng mga notification, kabilang ang mga na-post ng iba pang apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e2c505b..21fe6d4 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Uygulamaya, ağ politikalarını yönetme ve uygulamaya özgü kuralları tanımlama izni verir."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ağ kullanım hesaplamasını değiştir"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Uygulamaya, ağın uygulamalara göre nasıl kullanılacağını değiştirme izni verir. Normal uygulamalar tarafından kullanılmak için değildir."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"bildirimlere eriş"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Uygulamanın bildirimler almasına, bildirimleri incelemesine ve temizlemesine izin verir. Buna diğer uygulamalar tarafından yayınlanan bildirimler de dahildir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri denetleme."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0563f8c..7f80706 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Дозволяє програмі керувати політикою мережі та визначити спеціальні правила для програм."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"змінювати облік використання мережі"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дозволяє програмі змінювати метод підрахунку того, як програми використовують мережу. Не для використання звичайними програмами."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"отримувати доступ до сповіщень"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозволяє програмі отримувати, перевіряти й очищати сповіщення, зокрема опубліковані іншими програмами."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролювати довжину паролів для розблокування екрана та дозволені в них символи."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e4da91a..1406064 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允许应用管理网络政策和定义专门针对应用的规则。"</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改网络使用情况记录方式"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允许该应用修改对于各应用的网络使用情况的统计方式。普通应用不应使用此权限。"</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"查看通知"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"允许该应用检索、检查并清除通知,包括其他应用发布的通知。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 757ed6c..30893c6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -617,10 +617,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ivumela insiza ukuthi yengamele iigomo iphinde ichaze imithetho ehambisana ngqo nensiza."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"lungisa ukubala kokusebenza kohleloxhumano"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ivumela insiza ukuthi iguqule ukuthii ukusetshenziswa kwenethiwekhi kumiswa kanjani ezinsizeni. Ayisetshenziswa izinsiza ezijwayelekile."</string>
-    <!-- no translation found for permlab_accessNotifications (7673416487873432268) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNotifications (458457742683431387) -->
-    <skip />
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"finyelela kuzaziso"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ivumela uhlelo lokusebenza ukuthi lithole, lihlole, liphinde lisuse izaziso, ezifaka lezo ezithunyelwe ezinye izinhlelo zokusebenza."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 649e39d..0461c0b 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -213,8 +213,8 @@
                         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
                         // Initialize other fields.
                         config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
-                        config.enterpriseConfig.setCaCertificate("");
-                        config.enterpriseConfig.setClientCertificate("");
+                        config.enterpriseConfig.setCaCertificateAlias("");
+                        config.enterpriseConfig.setClientCertificateAlias("");
                         config.enterpriseConfig.setIdentity("");
                         config.enterpriseConfig.setAnonymousIdentity("");
                         break;
@@ -288,12 +288,12 @@
             }
             if (cacert) {
                 String cacertValue = new String(ch, start, length);
-                config.enterpriseConfig.setCaCertificate(cacertValue);
+                config.enterpriseConfig.setCaCertificateAlias(cacertValue);
                 cacert = false;
             }
             if (usercert) {
                 String usercertValue = new String(ch, start, length);
-                config.enterpriseConfig.setClientCertificate(usercertValue);
+                config.enterpriseConfig.setClientCertificateAlias(usercertValue);
                 usercert = false;
             }
             if (ip) {
diff --git a/docs/html/reference/gcm-lists.js b/docs/html/reference/gcm-lists.js
new file mode 100644
index 0000000..44c6023
--- /dev/null
+++ b/docs/html/reference/gcm-lists.js
@@ -0,0 +1,16 @@
+var GCM_DATA = [
+      { id:0, label:"com.google.android.gcm", link:"reference/com/google/android/gcm/package-summary.html", type:"package" },
+      { id:1, label:"com.google.android.gcm.GCMBaseIntentService", link:"reference/com/google/android/gcm/GCMBaseIntentService.html", type:"class" },
+      { id:2, label:"com.google.android.gcm.GCMBroadcastReceiver", link:"reference/com/google/android/gcm/GCMBroadcastReceiver.html", type:"class" },
+      { id:3, label:"com.google.android.gcm.GCMConstants", link:"reference/com/google/android/gcm/GCMConstants.html", type:"class" },
+      { id:4, label:"com.google.android.gcm.GCMRegistrar", link:"reference/com/google/android/gcm/GCMRegistrar.html", type:"class" },
+      { id:5, label:"com.google.android.gcm.server", link:"reference/com/google/android/gcm/server/package-summary.html", type:"package" },
+      { id:6, label:"com.google.android.gcm.server.Constants", link:"reference/com/google/android/gcm/server/Constants.html", type:"class" },
+      { id:7, label:"com.google.android.gcm.server.InvalidRequestException", link:"reference/com/google/android/gcm/server/InvalidRequestException.html", type:"class" },
+      { id:8, label:"com.google.android.gcm.server.Message", link:"reference/com/google/android/gcm/server/Message.html", type:"class" },
+      { id:9, label:"com.google.android.gcm.server.Message.Builder", link:"reference/com/google/android/gcm/server/Message.Builder.html", type:"class" },
+      { id:10, label:"com.google.android.gcm.server.MulticastResult", link:"reference/com/google/android/gcm/server/MulticastResult.html", type:"class" },
+      { id:11, label:"com.google.android.gcm.server.Result", link:"reference/com/google/android/gcm/server/Result.html", type:"class" },
+      { id:12, label:"com.google.android.gcm.server.Sender", link:"reference/com/google/android/gcm/server/Sender.html", type:"class" }
+
+    ];
diff --git a/docs/html/reference/gms-lists.js b/docs/html/reference/gms-lists.js
new file mode 100644
index 0000000..a5999f7
--- /dev/null
+++ b/docs/html/reference/gms-lists.js
@@ -0,0 +1,93 @@
+var GMS_DATA = [
+      { id:0, label:"com.google.android.gms", link:"reference/com/google/android/gms/package-summary.html", type:"package" },
+      { id:1, label:"com.google.android.gms.R", link:"reference/com/google/android/gms/R.html", type:"class" },
+      { id:2, label:"com.google.android.gms.R.attr", link:"reference/com/google/android/gms/R.attr.html", type:"class" },
+      { id:3, label:"com.google.android.gms.R.id", link:"reference/com/google/android/gms/R.id.html", type:"class" },
+      { id:4, label:"com.google.android.gms.R.string", link:"reference/com/google/android/gms/R.string.html", type:"class" },
+      { id:5, label:"com.google.android.gms.R.styleable", link:"reference/com/google/android/gms/R.styleable.html", type:"class" },
+      { id:6, label:"com.google.android.gms.analytics", link:"reference/com/google/android/gms/analytics/package-summary.html", type:"package" },
+      { id:7, label:"com.google.android.gms.analytics.CampaignTrackingReceiver", link:"reference/com/google/android/gms/analytics/CampaignTrackingReceiver.html", type:"class" },
+      { id:8, label:"com.google.android.gms.analytics.CampaignTrackingService", link:"reference/com/google/android/gms/analytics/CampaignTrackingService.html", type:"class" },
+      { id:9, label:"com.google.android.gms.analytics.EasyTracker", link:"reference/com/google/android/gms/analytics/EasyTracker.html", type:"class" },
+      { id:10, label:"com.google.android.gms.analytics.ExceptionParser", link:"reference/com/google/android/gms/analytics/ExceptionParser.html", type:"class" },
+      { id:11, label:"com.google.android.gms.analytics.GoogleAnalytics", link:"reference/com/google/android/gms/analytics/GoogleAnalytics.html", type:"class" },
+      { id:12, label:"com.google.android.gms.analytics.GoogleAnalytics.AppOptOutCallback", link:"reference/com/google/android/gms/analytics/GoogleAnalytics.AppOptOutCallback.html", type:"class" },
+      { id:13, label:"com.google.android.gms.analytics.ModelFields", link:"reference/com/google/android/gms/analytics/ModelFields.html", type:"class" },
+      { id:14, label:"com.google.android.gms.analytics.StandardExceptionParser", link:"reference/com/google/android/gms/analytics/StandardExceptionParser.html", type:"class" },
+      { id:15, label:"com.google.android.gms.analytics.Tracker", link:"reference/com/google/android/gms/analytics/Tracker.html", type:"class" },
+      { id:16, label:"com.google.android.gms.analytics.Transaction", link:"reference/com/google/android/gms/analytics/Transaction.html", type:"class" },
+      { id:17, label:"com.google.android.gms.analytics.Transaction.Builder", link:"reference/com/google/android/gms/analytics/Transaction.Builder.html", type:"class" },
+      { id:18, label:"com.google.android.gms.analytics.Transaction.Item", link:"reference/com/google/android/gms/analytics/Transaction.Item.html", type:"class" },
+      { id:19, label:"com.google.android.gms.analytics.Transaction.Item.Builder", link:"reference/com/google/android/gms/analytics/Transaction.Item.Builder.html", type:"class" },
+      { id:20, label:"com.google.android.gms.auth", link:"reference/com/google/android/gms/auth/package-summary.html", type:"package" },
+      { id:21, label:"com.google.android.gms.auth.GoogleAuthException", link:"reference/com/google/android/gms/auth/GoogleAuthException.html", type:"class" },
+      { id:22, label:"com.google.android.gms.auth.GoogleAuthUtil", link:"reference/com/google/android/gms/auth/GoogleAuthUtil.html", type:"class" },
+      { id:23, label:"com.google.android.gms.auth.GooglePlayServicesAvailabilityException", link:"reference/com/google/android/gms/auth/GooglePlayServicesAvailabilityException.html", type:"class" },
+      { id:24, label:"com.google.android.gms.auth.UserRecoverableAuthException", link:"reference/com/google/android/gms/auth/UserRecoverableAuthException.html", type:"class" },
+      { id:25, label:"com.google.android.gms.auth.UserRecoverableNotifiedException", link:"reference/com/google/android/gms/auth/UserRecoverableNotifiedException.html", type:"class" },
+      { id:26, label:"com.google.android.gms.common", link:"reference/com/google/android/gms/common/package-summary.html", type:"package" },
+      { id:27, label:"com.google.android.gms.common.AccountPicker", link:"reference/com/google/android/gms/common/AccountPicker.html", type:"class" },
+      { id:28, label:"com.google.android.gms.common.ConnectionResult", link:"reference/com/google/android/gms/common/ConnectionResult.html", type:"class" },
+      { id:29, label:"com.google.android.gms.common.GooglePlayServicesClient", link:"reference/com/google/android/gms/common/GooglePlayServicesClient.html", type:"class" },
+      { id:30, label:"com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks", link:"reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html", type:"class" },
+      { id:31, label:"com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener", link:"reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html", type:"class" },
+      { id:32, label:"com.google.android.gms.common.GooglePlayServicesNotAvailableException", link:"reference/com/google/android/gms/common/GooglePlayServicesNotAvailableException.html", type:"class" },
+      { id:33, label:"com.google.android.gms.common.GooglePlayServicesUtil", link:"reference/com/google/android/gms/common/GooglePlayServicesUtil.html", type:"class" },
+      { id:34, label:"com.google.android.gms.common.Scopes", link:"reference/com/google/android/gms/common/Scopes.html", type:"class" },
+      { id:35, label:"com.google.android.gms.maps", link:"reference/com/google/android/gms/maps/package-summary.html", type:"package" },
+      { id:36, label:"com.google.android.gms.maps.CameraUpdate", link:"reference/com/google/android/gms/maps/CameraUpdate.html", type:"class" },
+      { id:37, label:"com.google.android.gms.maps.CameraUpdateFactory", link:"reference/com/google/android/gms/maps/CameraUpdateFactory.html", type:"class" },
+      { id:38, label:"com.google.android.gms.maps.GoogleMap", link:"reference/com/google/android/gms/maps/GoogleMap.html", type:"class" },
+      { id:39, label:"com.google.android.gms.maps.GoogleMap.CancelableCallback", link:"reference/com/google/android/gms/maps/GoogleMap.CancelableCallback.html", type:"class" },
+      { id:40, label:"com.google.android.gms.maps.GoogleMap.InfoWindowAdapter", link:"reference/com/google/android/gms/maps/GoogleMap.InfoWindowAdapter.html", type:"class" },
+      { id:41, label:"com.google.android.gms.maps.GoogleMap.OnCameraChangeListener", link:"reference/com/google/android/gms/maps/GoogleMap.OnCameraChangeListener.html", type:"class" },
+      { id:42, label:"com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener", link:"reference/com/google/android/gms/maps/GoogleMap.OnInfoWindowClickListener.html", type:"class" },
+      { id:43, label:"com.google.android.gms.maps.GoogleMap.OnMapClickListener", link:"reference/com/google/android/gms/maps/GoogleMap.OnMapClickListener.html", type:"class" },
+      { id:44, label:"com.google.android.gms.maps.GoogleMap.OnMapLongClickListener", link:"reference/com/google/android/gms/maps/GoogleMap.OnMapLongClickListener.html", type:"class" },
+      { id:45, label:"com.google.android.gms.maps.GoogleMap.OnMarkerClickListener", link:"reference/com/google/android/gms/maps/GoogleMap.OnMarkerClickListener.html", type:"class" },
+      { id:46, label:"com.google.android.gms.maps.GoogleMap.OnMarkerDragListener", link:"reference/com/google/android/gms/maps/GoogleMap.OnMarkerDragListener.html", type:"class" },
+      { id:47, label:"com.google.android.gms.maps.GoogleMapOptions", link:"reference/com/google/android/gms/maps/GoogleMapOptions.html", type:"class" },
+      { id:48, label:"com.google.android.gms.maps.LocationSource", link:"reference/com/google/android/gms/maps/LocationSource.html", type:"class" },
+      { id:49, label:"com.google.android.gms.maps.LocationSource.OnLocationChangedListener", link:"reference/com/google/android/gms/maps/LocationSource.OnLocationChangedListener.html", type:"class" },
+      { id:50, label:"com.google.android.gms.maps.MapFragment", link:"reference/com/google/android/gms/maps/MapFragment.html", type:"class" },
+      { id:51, label:"com.google.android.gms.maps.MapView", link:"reference/com/google/android/gms/maps/MapView.html", type:"class" },
+      { id:52, label:"com.google.android.gms.maps.MapsInitializer", link:"reference/com/google/android/gms/maps/MapsInitializer.html", type:"class" },
+      { id:53, label:"com.google.android.gms.maps.Projection", link:"reference/com/google/android/gms/maps/Projection.html", type:"class" },
+      { id:54, label:"com.google.android.gms.maps.SupportMapFragment", link:"reference/com/google/android/gms/maps/SupportMapFragment.html", type:"class" },
+      { id:55, label:"com.google.android.gms.maps.UiSettings", link:"reference/com/google/android/gms/maps/UiSettings.html", type:"class" },
+      { id:56, label:"com.google.android.gms.maps.model", link:"reference/com/google/android/gms/maps/model/package-summary.html", type:"package" },
+      { id:57, label:"com.google.android.gms.maps.model.BitmapDescriptor", link:"reference/com/google/android/gms/maps/model/BitmapDescriptor.html", type:"class" },
+      { id:58, label:"com.google.android.gms.maps.model.BitmapDescriptorFactory", link:"reference/com/google/android/gms/maps/model/BitmapDescriptorFactory.html", type:"class" },
+      { id:59, label:"com.google.android.gms.maps.model.CameraPosition", link:"reference/com/google/android/gms/maps/model/CameraPosition.html", type:"class" },
+      { id:60, label:"com.google.android.gms.maps.model.CameraPosition.Builder", link:"reference/com/google/android/gms/maps/model/CameraPosition.Builder.html", type:"class" },
+      { id:61, label:"com.google.android.gms.maps.model.GroundOverlay", link:"reference/com/google/android/gms/maps/model/GroundOverlay.html", type:"class" },
+      { id:62, label:"com.google.android.gms.maps.model.GroundOverlayOptions", link:"reference/com/google/android/gms/maps/model/GroundOverlayOptions.html", type:"class" },
+      { id:63, label:"com.google.android.gms.maps.model.LatLng", link:"reference/com/google/android/gms/maps/model/LatLng.html", type:"class" },
+      { id:64, label:"com.google.android.gms.maps.model.LatLngBounds", link:"reference/com/google/android/gms/maps/model/LatLngBounds.html", type:"class" },
+      { id:65, label:"com.google.android.gms.maps.model.LatLngBounds.Builder", link:"reference/com/google/android/gms/maps/model/LatLngBounds.Builder.html", type:"class" },
+      { id:66, label:"com.google.android.gms.maps.model.Marker", link:"reference/com/google/android/gms/maps/model/Marker.html", type:"class" },
+      { id:67, label:"com.google.android.gms.maps.model.MarkerOptions", link:"reference/com/google/android/gms/maps/model/MarkerOptions.html", type:"class" },
+      { id:68, label:"com.google.android.gms.maps.model.Polygon", link:"reference/com/google/android/gms/maps/model/Polygon.html", type:"class" },
+      { id:69, label:"com.google.android.gms.maps.model.PolygonOptions", link:"reference/com/google/android/gms/maps/model/PolygonOptions.html", type:"class" },
+      { id:70, label:"com.google.android.gms.maps.model.Polyline", link:"reference/com/google/android/gms/maps/model/Polyline.html", type:"class" },
+      { id:71, label:"com.google.android.gms.maps.model.PolylineOptions", link:"reference/com/google/android/gms/maps/model/PolylineOptions.html", type:"class" },
+      { id:72, label:"com.google.android.gms.maps.model.RuntimeRemoteException", link:"reference/com/google/android/gms/maps/model/RuntimeRemoteException.html", type:"class" },
+      { id:73, label:"com.google.android.gms.maps.model.Tile", link:"reference/com/google/android/gms/maps/model/Tile.html", type:"class" },
+      { id:74, label:"com.google.android.gms.maps.model.TileOverlay", link:"reference/com/google/android/gms/maps/model/TileOverlay.html", type:"class" },
+      { id:75, label:"com.google.android.gms.maps.model.TileOverlayOptions", link:"reference/com/google/android/gms/maps/model/TileOverlayOptions.html", type:"class" },
+      { id:76, label:"com.google.android.gms.maps.model.TileProvider", link:"reference/com/google/android/gms/maps/model/TileProvider.html", type:"class" },
+      { id:77, label:"com.google.android.gms.maps.model.UrlTileProvider", link:"reference/com/google/android/gms/maps/model/UrlTileProvider.html", type:"class" },
+      { id:78, label:"com.google.android.gms.maps.model.VisibleRegion", link:"reference/com/google/android/gms/maps/model/VisibleRegion.html", type:"class" },
+      { id:79, label:"com.google.android.gms.panorama", link:"reference/com/google/android/gms/panorama/package-summary.html", type:"package" },
+      { id:80, label:"com.google.android.gms.panorama.PanoramaClient", link:"reference/com/google/android/gms/panorama/PanoramaClient.html", type:"class" },
+      { id:81, label:"com.google.android.gms.panorama.PanoramaClient.OnPanoramaInfoLoadedListener", link:"reference/com/google/android/gms/panorama/PanoramaClient.OnPanoramaInfoLoadedListener.html", type:"class" },
+      { id:82, label:"com.google.android.gms.plus", link:"reference/com/google/android/gms/plus/package-summary.html", type:"package" },
+      { id:83, label:"com.google.android.gms.plus.GooglePlusUtil", link:"reference/com/google/android/gms/plus/GooglePlusUtil.html", type:"class" },
+      { id:84, label:"com.google.android.gms.plus.PlusClient", link:"reference/com/google/android/gms/plus/PlusClient.html", type:"class" },
+      { id:85, label:"com.google.android.gms.plus.PlusOneButton", link:"reference/com/google/android/gms/plus/PlusOneButton.html", type:"class" },
+      { id:86, label:"com.google.android.gms.plus.PlusOneButton.OnPlusOneClickListener", link:"reference/com/google/android/gms/plus/PlusOneButton.OnPlusOneClickListener.html", type:"class" },
+      { id:87, label:"com.google.android.gms.plus.PlusShare", link:"reference/com/google/android/gms/plus/PlusShare.html", type:"class" },
+      { id:88, label:"com.google.android.gms.plus.PlusShare.Builder", link:"reference/com/google/android/gms/plus/PlusShare.Builder.html", type:"class" },
+      { id:89, label:"com.google.android.gms.plus.PlusSignInButton", link:"reference/com/google/android/gms/plus/PlusSignInButton.html", type:"class" }
+
+    ];
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index cb9d2ef..dff3a32 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -3,43 +3,44 @@
 header.hide=1
 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 
-sdk.win32_bundle_download=adt-bundle-windows-x86.zip
-sdk.win32_bundle_bytes=418030942
-sdk.win32_bundle_checksum=ce32861d8f7c93ff6ff6971bd99d228e
-
-sdk.win64_bundle_download=adt-bundle-windows-x86_64.zip
-sdk.win64_bundle_bytes=418155677
-sdk.win64_bundle_checksum=f09aa4557bd1dc2703fde95dcdd6b92e
-
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64.zip
-sdk.mac64_bundle_bytes=383216991
-sdk.mac64_bundle_checksum=ea6c074ee30c426c503dab5c225a5076
 
 sdk.linux32_bundle_download=adt-bundle-linux-x86.zip
-sdk.linux32_bundle_bytes=411205048
-sdk.linux32_bundle_checksum=e64594cd339b8d9a400b9d16c616b3c3
+sdk.linux32_bundle_bytes=418614971
+sdk.linux32_bundle_checksum=24506708af221a887326c2a9ca9625dc
 
 sdk.linux64_bundle_download=adt-bundle-linux-x86_64.zip
-sdk.linux64_bundle_bytes=411478695
-sdk.linux64_bundle_checksum=582bfc9083ff4cbcfacc8223bd8c3be1
+sdk.linux64_bundle_bytes=418889835
+sdk.linux64_bundle_checksum=464c1fbe92ea293d6b2292c27af5066a
+
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64.zip
+sdk.mac64_bundle_bytes=390649300
+sdk.mac64_bundle_checksum=f557bc61a4bff466633037839771bffb
+
+sdk.win32_bundle_download=adt-bundle-windows-x86.zip
+sdk.win32_bundle_bytes=425429957
+sdk.win32_bundle_checksum=cca97f12904774385a57d542e70a490f
+
+sdk.win64_bundle_download=adt-bundle-windows-x86_64.zip
+sdk.win64_bundle_bytes=425553759
+sdk.win64_bundle_checksum=c51679f4517e1c3ddefa1e662bbf17f6
 
 
 
-sdk.win_installer=installer_r21.0.1-windows.exe
-sdk.win_installer_bytes=76520869
-sdk.win_installer_checksum=e2012262471a2583d4a559b15fcf45ff
+sdk.linux_download=android-sdk_r21.1.0-linux.tgz
+sdk.linux_bytes=91617112
+sdk.linux_checksum=3369a439240cf3dbe165d6b4173900a8
 
-sdk.win_download=android-sdk_r21.0.1-windows.zip
-sdk.win_bytes=99107847
-sdk.win_checksum=613568d774c3bf25c5d24db16601af83
+sdk.mac_download=android-sdk_r21.1.0-macosx.zip
+sdk.mac_bytes=66077080
+sdk.mac_checksum=49903cf79e1f8e3fde54a95bd3666385
 
-sdk.mac_download=android-sdk_r21.0.1-macosx.zip
-sdk.mac_bytes=65804128
-sdk.mac_checksum=30401c43a014cd5d6ec9d0c62854a1d9
+sdk.win_download=android-sdk_r21.1.0-windows.zip
+sdk.win_bytes=99360755
+sdk.win_checksum=dbece8859da9b66a1e8e7cd47b1e647e
 
-sdk.linux_download=android-sdk_r21.0.1-linux.tgz
-sdk.linux_bytes=91394975
-sdk.linux_checksum=eaa5a8d76d692d1d027f2bbcee019644
+sdk.win_installer=installer_r21.1.0-windows.exe
+sdk.win_installer_bytes=77767013
+sdk.win_installer_checksum=594d8ff8e349db9e783a5f2229561353
 
 
 
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 804030b..d956af2 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
 adt.zip.version=21.0.1
-adt.zip.download=ADT-21.0.1.zip
-adt.zip.bytes=13569302
-adt.zip.checksum=acfb01bf3fd1240f1fc21488c3dd16bf
+adt.zip.download=ADT-21.1.0.zip
+adt.zip.bytes=13564671
+adt.zip.checksum=f1ae183891229784bb9c33bcc9c5ef1e
 
 @jd:body
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 243683c..4adb7b2 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -57,6 +57,63 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 21.1.0</a> <em>(February 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required for ADT 21.1.0.</li>
+      <li>Eclipse Helios (Version 3.6.2) or higher is required for ADT 21.1.0.</li>
+      <li>ADT 21.1.0 is designed for use with <a href="{@docRoot}tools/sdk/tools-notes.html">SDK
+      Tools r21.1.0</a>. If you haven't already installed SDK Tools r21.1.0 into your SDK, use the
+      Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Added new <a href="{@docRoot}tools/projects/templates.html">code templates</a> for
+        notifications, blank fragments and list fragments.</li>
+      <li>Added support for resource rename refactoring. Renaming a resource XML file, drawable
+        icon, an {@code R.} field name or ID in the layout editor invokes a refactoring routine
+        to update all resource references.</li>
+      <li>Added more than 15 new Lint checks, including checks for overriding older APIs, XML
+        resource problems, graphic asset issues and manifest tags.
+      <li>Updated XML Editor to respond to refactoring shortcut keys such as <strong>Refactor
+        &gt; Rename</strong>.</li>
+      <li>Updated XML Editor to improve double click handling.</li>
+      <li>Added code completion improvements for custom views, theme references and class
+        references. For example, code completion in a {@code &lt;fragment android:name=””&gt;} tag
+        now suggests completion with a list of fragment classes. Similarly, code completion in the
+        manifest now offers implementations suitable for the given tag.</li>
+      <li>Updated the <strong>Project Import</strong> dialog so that it shows a table for all
+        imported projects where you can edit the name of the imported project.</li>
+      <li>Added support for layout aliases in the Layout Editor.</li>
+    </ul>
+  </dd>
+
+  <dt>Bug fixes:</dt>
+  <dd>
+    <ul>
+      <li>Fixed issued with refactoring support for renaming and moving classes and packages.
+      </li>
+    </ul>
+  </dd>
+
+</dl>
+</div>
+</div>
+
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 21.0.1</a> <em>(December 2012)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 9349a4e..a5b7eee 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -28,6 +28,41 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 21.1.0</a> <em>(February 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 16 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that the SDK Tools r21.1.0 is
+          designed for use with ADT 21.1.0 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 21.1.0.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+    </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Improved error reporting in {@code dx} when dex merging fails in the build
+          system.</li>
+        <li>Added more than 15 new Lint checks, including checks for overriding older APIs, XML
+          resource problems, graphic asset issues and manifest tags.</li>
+        <li>Added new aapt feature to compile resources.</li>
+      </ul>
+    </dd>
+    </dl>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 21.0.1</a> <em>(December 2012)</em>
   </p>
 
@@ -40,7 +75,7 @@
         <li>Android SDK Platform-tools revision 16 or later.</li>
         <li>If you are developing in Eclipse with ADT, note that the SDK Tools r21.0.1 is
           designed for use with ADT 21.0.1 and later. If you haven't already, update your
-        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 21.0.0.</li>
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 21.0.1.</li>
         <li>If you are developing outside Eclipse, you must have
           <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
     </ul>
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 5f0844a..1c83c51 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -488,7 +488,11 @@
      */
     public void copyFromUnchecked(int[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        }
     }
     /**
      * Copy an allocation from an array.  This variant is not type
@@ -499,7 +503,11 @@
      */
     public void copyFromUnchecked(short[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        }
     }
     /**
      * Copy an allocation from an array.  This variant is not type
@@ -510,7 +518,11 @@
      */
     public void copyFromUnchecked(byte[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        }
     }
     /**
      * Copy an allocation from an array.  This variant is not type
@@ -521,7 +533,11 @@
      */
     public void copyFromUnchecked(float[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFromUnchecked(0, mCurrentCount, d);
+        }
     }
 
     /**
@@ -533,7 +549,11 @@
      */
     public void copyFrom(int[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFrom(0, mCurrentCount, d);
+        }
     }
 
     /**
@@ -545,7 +565,11 @@
      */
     public void copyFrom(short[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFrom(0, mCurrentCount, d);
+        }
     }
 
     /**
@@ -557,7 +581,11 @@
      */
     public void copyFrom(byte[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFrom(0, mCurrentCount, d);
+        }
     }
 
     /**
@@ -569,7 +597,11 @@
      */
     public void copyFrom(float[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mCurrentCount, d);
+        if (mCurrentDimY > 0) {
+            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
+        } else {
+            copy1DRangeFrom(0, mCurrentCount, d);
+        }
     }
 
     /**
@@ -827,6 +859,35 @@
         }
     }
 
+    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, byte[] data) {
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length);
+    }
+
+    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) {
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length * 2);
+    }
+
+    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) {
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length * 4);
+    }
+
+    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) {
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length * 4);
+    }
+
+
     /**
      * Copy a rectangular region from the array into the allocation.
      * The incoming array is assumed to be tightly packed.
@@ -838,31 +899,23 @@
      * @param data to be placed into the allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length);
+        validateIsInt8();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 2);
+        validateIsInt16();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 4);
+        validateIsInt32();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, data, data.length * 4);
+        validateIsFloat32();
+        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
     }
 
     /**
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index a215a57..0a7e882 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,6 +29,12 @@
         mData = new byte[len];
     }
 
+    public FieldPacker(byte[] data) {
+        mPos = 0;
+        mLen = data.length;
+        mData = data;
+    }
+
     public void align(int v) {
         if ((v <= 0) || ((v & (v - 1)) != 0)) {
             throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v);
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index b53ba0d..b405588 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -171,6 +171,11 @@
             throw new RSIllegalArgumentException(
                 "At least one of ain or aout is required to be non-null.");
         }
+
+        if (sc == null) {
+            forEach(slot, ain, aout, v);
+            return;
+        }
         int in_id = 0;
         if (ain != null) {
             in_id = ain.getID(mRS);
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 48f5bf3..5b45d70 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -855,6 +855,7 @@
         DENSITY_HIGH = ACONFIGURATION_DENSITY_HIGH,
         DENSITY_XHIGH = ACONFIGURATION_DENSITY_XHIGH,
         DENSITY_XXHIGH = ACONFIGURATION_DENSITY_XXHIGH,
+        DENSITY_XXXHIGH = ACONFIGURATION_DENSITY_XXXHIGH,
         DENSITY_NONE = ACONFIGURATION_DENSITY_NONE
     };
     
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 08e2332..62f268d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1179,6 +1179,10 @@
 
             delete bounds;
         }
+        // We must clear the list of dirty rects before we
+        // call setupDraw() to prevent stencil setup to do
+        // the same thing again
+        mLayers.clear();
 
         setupDraw(false);
         setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
@@ -1195,9 +1199,8 @@
         for (uint32_t i = 0; i < count; i++) {
             delete mLayers.itemAt(i);
         }
+        mLayers.clear();
     }
-
-    mLayers.clear();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 1afcb46..1a75ea8 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -189,7 +189,10 @@
     vOffset += glyph->mBitmapTop + height;
 
     SkPoint destination[4];
-    measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent);
+    bool ok = measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent);
+    if (!ok) {
+        ALOGW("The path for drawTextOnPath is empty or null");
+    }
 
     // Move along the tangent and offset by the normal
     destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset,
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index f930a03..5d27966 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -19,7 +19,6 @@
 #define LOG_TAG "MediaScannerJNI"
 #include <utils/Log.h>
 #include <utils/threads.h>
-#include <utils/Unicode.h>
 #include <media/mediascanner.h>
 #include <media/stagefright/StagefrightMediaScanner.h>
 
@@ -57,6 +56,53 @@
     return OK;
 }
 
+// stolen from dalvik/vm/checkJni.cpp
+static bool isValidUtf8(const char* bytes) {
+    while (*bytes != '\0') {
+        unsigned char utf8 = *(bytes++);
+        // Switch on the high four bits.
+        switch (utf8 >> 4) {
+        case 0x00:
+        case 0x01:
+        case 0x02:
+        case 0x03:
+        case 0x04:
+        case 0x05:
+        case 0x06:
+        case 0x07:
+            // Bit pattern 0xxx. No need for any extra bytes.
+            break;
+        case 0x08:
+        case 0x09:
+        case 0x0a:
+        case 0x0b:
+        case 0x0f:
+            /*
+             * Bit pattern 10xx or 1111, which are illegal start bytes.
+             * Note: 1111 is valid for normal UTF-8, but not the
+             * modified UTF-8 used here.
+             */
+            return false;
+        case 0x0e:
+            // Bit pattern 1110, so there are two additional bytes.
+            utf8 = *(bytes++);
+            if ((utf8 & 0xc0) != 0x80) {
+                return false;
+            }
+            // Fall through to take care of the final byte.
+        case 0x0c:
+        case 0x0d:
+            // Bit pattern 110x, so there is one additional byte.
+            utf8 = *(bytes++);
+            if ((utf8 & 0xc0) != 0x80) {
+                return false;
+            }
+            break;
+        }
+    }
+    return true;
+}
+
 class MyMediaScannerClient : public MediaScannerClient
 {
 public:
@@ -124,11 +170,8 @@
             mEnv->ExceptionClear();
             return NO_MEMORY;
         }
-
-        // Check if the value is valid UTF-8 string and replace
-        // any un-printable characters with '?' when it's not.
         char *cleaned = NULL;
-        if (utf8_length(value) == -1) {
+        if (!isValidUtf8(value)) {
             cleaned = strdup(value);
             char *chp = cleaned;
             char ch;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index dc54eae..e79b2c6 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -45,6 +45,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
@@ -162,7 +164,7 @@
             if (convertView == null) {
                 convertView = createView(parent);
             }
-            ViewHolder holder = (ViewHolder) convertView.getTag();
+            final ViewHolder holder = (ViewHolder) convertView.getTag();
 
             // index is reverse since most recent appears at the bottom...
             final int index = mRecentTaskDescriptions.size() - position - 1;
@@ -191,24 +193,49 @@
                             holder.calloutLine.setTranslationY(0f);
                         }
                     }
-                    mItemToAnimateInWhenWindowAnimationIsFinished = holder;
-                    final int translation = -getResources().getDimensionPixelSize(
-                            R.dimen.status_bar_recents_app_icon_translate_distance);
-                    final Configuration config = getResources().getConfiguration();
-                    if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
-                        holder.iconView.setAlpha(0f);
-                        holder.iconView.setTranslationX(translation);
-                        holder.labelView.setAlpha(0f);
-                        holder.labelView.setTranslationX(translation);
-                        holder.calloutLine.setAlpha(0f);
-                        holder.calloutLine.setTranslationX(translation);
-                    } else {
-                        holder.iconView.setAlpha(0f);
-                        holder.iconView.setTranslationY(translation);
-                    }
-                    if (!mWaitingForWindowAnimation) {
-                        animateInIconOfFirstTask();
-                    }
+                    mItemToAnimateInWhenWindowAnimationIsFinished = null;
+
+                    final ViewTreeObserver observer = getViewTreeObserver();
+                    final OnGlobalLayoutListener animateFirstIcon = new OnGlobalLayoutListener() {
+                        public void onGlobalLayout() {
+                            if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
+                                holder.iconView.setAlpha(1f);
+                                holder.iconView.setTranslationX(0f);
+                                holder.iconView.setTranslationY(0f);
+                                holder.labelView.setAlpha(1f);
+                                holder.labelView.setTranslationX(0f);
+                                holder.labelView.setTranslationY(0f);
+                                if (holder.calloutLine != null) {
+                                    holder.calloutLine.setAlpha(1f);
+                                    holder.calloutLine.setTranslationX(0f);
+                                    holder.calloutLine.setTranslationY(0f);
+                                }
+                            }
+                            mItemToAnimateInWhenWindowAnimationIsFinished = holder;
+                            int translation = -getResources().getDimensionPixelSize(
+                                    R.dimen.status_bar_recents_app_icon_translate_distance);
+                            final Configuration config = getResources().getConfiguration();
+                            if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                                if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+                                    translation = -translation;
+                                }
+                                holder.iconView.setAlpha(0f);
+                                holder.iconView.setTranslationX(translation);
+                                holder.labelView.setAlpha(0f);
+                                holder.labelView.setTranslationX(translation);
+                                holder.calloutLine.setAlpha(0f);
+                                holder.calloutLine.setTranslationX(translation);
+                            } else {
+                                holder.iconView.setAlpha(0f);
+                                holder.iconView.setTranslationY(translation);
+                            }
+                            if (!mWaitingForWindowAnimation) {
+                                animateInIconOfFirstTask();
+                            }
+                            getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        }
+                    };
+                    observer.addOnGlobalLayoutListener(animateFirstIcon);
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 3bac146..f941f89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -597,6 +597,10 @@
                     y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin
                             + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
                 }
+                if (mLayoutDirection == View.LAYOUT_DIRECTION_RTL) {
+                    x = dm.widthPixels - x - res
+                            .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
+                }
 
                 ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
                         getStatusBarView(),
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 88ea1f1..dfde692 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -133,7 +133,7 @@
 
 class BackupManagerService extends IBackupManager.Stub {
     private static final String TAG = "BackupManagerService";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
     private static final boolean MORE_DEBUG = false;
 
     // Name and current contents version of the full-backup manifest file
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 1a2c3de..13bf39f 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -235,6 +235,31 @@
                 }
             };
         }
+
+        public StatusBarNotification[] getArray(int count) {
+            if (count == 0) count = Archive.BUFFER_SIZE;
+            final StatusBarNotification[] a
+                    = new StatusBarNotification[Math.min(count, mBuffer.size())];
+            Iterator<StatusBarNotification> iter = descendingIterator();
+            int i=0;
+            while (iter.hasNext() && i < count) {
+                a[i++] = iter.next();
+            }
+            return a;
+        }
+
+        public StatusBarNotification[] getArray(int count, String pkg, int userId) {
+            if (count == 0) count = Archive.BUFFER_SIZE;
+            final StatusBarNotification[] a
+                    = new StatusBarNotification[Math.min(count, mBuffer.size())];
+            Iterator<StatusBarNotification> iter = filter(descendingIterator(), pkg, userId);
+            int i=0;
+            while (iter.hasNext() && i < count) {
+                a[i++] = iter.next();
+            }
+            return a;
+        }
+
     }
 
     Archive mArchive = new Archive();
@@ -347,10 +372,9 @@
 
     public StatusBarNotification[] getActiveNotifications(String callingPkg) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
-                "NotificationManagerService");
+                "NotificationManagerService.getActiveNotifications");
 
         StatusBarNotification[] tmp = null;
-        int userId = UserHandle.getCallingUserId();
         int uid = Binder.getCallingUid();
 
         if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
@@ -366,6 +390,22 @@
         return tmp;
     }
 
+    public StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NOTIFICATIONS,
+                "NotificationManagerService.getHistoricalNotifications");
+
+        StatusBarNotification[] tmp = null;
+        int uid = Binder.getCallingUid();
+
+        if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
+                == AppOpsManager.MODE_ALLOWED) {
+            synchronized (mArchive) {
+                tmp = mArchive.getArray(count);
+            }
+        }
+        return tmp;
+    }
+
     public static final class NotificationRecord
     {
         final StatusBarNotification sbn;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 608ad1c..22af3d5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2838,11 +2838,8 @@
             for (int i=0; i<activities.size(); i++) {
                 ActivityRecord r = activities.get(i);
                 if (!r.finishing) {
-                    int index = mMainStack.indexOfTokenLocked(r.appToken);
-                    if (index >= 0) {
-                        mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
-                                null, "finish-heavy", true);
-                    }
+                    mMainStack.finishActivityLocked(r, Activity.RESULT_CANCELED,
+                            null, "finish-heavy", true);
                 }
             }
             
@@ -8002,33 +7999,7 @@
             }
             mMainStack.resumeTopActivityLocked(null);
         } else {
-            ActivityRecord r = mMainStack.topRunningActivityLocked(null);
-            if (r != null && r.app == app) {
-                // If the top running activity is from this crashing
-                // process, then terminate it to avoid getting in a loop.
-                Slog.w(TAG, "  Force finishing activity "
-                        + r.intent.getComponent().flattenToShortString());
-                int index = mMainStack.indexOfActivityLocked(r);
-                r.stack.finishActivityLocked(r, index,
-                        Activity.RESULT_CANCELED, null, "crashed", false);
-                // Also terminate any activities below it that aren't yet
-                // stopped, to avoid a situation where one will get
-                // re-start our crashing activity once it gets resumed again.
-                index--;
-                if (index >= 0) {
-                    r = mMainStack.getActivityAtIndex(index);
-                    if (r.state == ActivityState.RESUMED
-                            || r.state == ActivityState.PAUSING
-                            || r.state == ActivityState.PAUSED) {
-                        if (!r.isHomeActivity || mHomeProcess != r.app) {
-                            Slog.w(TAG, "  Force finishing activity "
-                                    + r.intent.getComponent().flattenToShortString());
-                            r.stack.finishActivityLocked(r, index,
-                                    Activity.RESULT_CANCELED, null, "crashed", false);
-                        }
-                    }
-                }
-            }
+            mMainStack.finishTopRunningActivityLocked(app);
         }
 
         // Bump up the crash count of any services currently running in the proc.
@@ -12370,7 +12341,6 @@
 
     public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
             Intent resultData) {
-        ComponentName dest = destIntent.getComponent();
 
         synchronized (this) {
             ActivityRecord srec = ActivityRecord.forToken(token);
@@ -12378,87 +12348,7 @@
                 return false;
             }
             ActivityStack stack = srec.stack;
-            final int start = stack.indexOfActivityLocked(srec);
-            if (start < 0) {
-                // Current activity is not in history stack; do nothing.
-                return false;
-            }
-            int finishTo = start - 1;
-            ActivityRecord parent = null;
-            boolean foundParentInTask = false;
-            if (dest != null) {
-                TaskRecord tr = srec.task;
-                for (int i = start - 1; i >= 0; i--) {
-                    ActivityRecord r = stack.getActivityAtIndex(i);
-                    if (tr != r.task) {
-                        // Couldn't find parent in the same task; stop at the one above this.
-                        // (Root of current task; in-app "home" behavior)
-                        // Always at least finish the current activity.
-                        finishTo = Math.min(start - 1, i + 1);
-                        parent = stack.getActivityAtIndex(finishTo);
-                        break;
-                    } else if (r.info.packageName.equals(dest.getPackageName()) &&
-                            r.info.name.equals(dest.getClassName())) {
-                        finishTo = i;
-                        parent = r;
-                        foundParentInTask = true;
-                        break;
-                    }
-                }
-            }
-
-            if (mController != null) {
-                ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
-                if (next != null) {
-                    // ask watcher if this is allowed
-                    boolean resumeOK = true;
-                    try {
-                        resumeOK = mController.activityResuming(next.packageName);
-                    } catch (RemoteException e) {
-                        mController = null;
-                    }
-
-                    if (!resumeOK) {
-                        return false;
-                    }
-                }
-            }
-            final long origId = Binder.clearCallingIdentity();
-            for (int i = start; i > finishTo; i--) {
-                ActivityRecord r = stack.getActivityAtIndex(i);
-                mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
-                        "navigate-up", true);
-                // Only return the supplied result for the first activity finished
-                resultCode = Activity.RESULT_CANCELED;
-                resultData = null;
-            }
-
-            if (parent != null && foundParentInTask) {
-                final int parentLaunchMode = parent.info.launchMode;
-                final int destIntentFlags = destIntent.getFlags();
-                if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
-                        parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
-                        parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
-                        (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
-                    parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
-                } else {
-                    try {
-                        ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
-                                destIntent.getComponent(), 0, srec.userId);
-                        int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
-                                null, aInfo, parent.appToken, null,
-                                0, -1, parent.launchedFromUid, parent.launchedFromPackage,
-                                0, null, true, null);
-                        foundParentInTask = res == ActivityManager.START_SUCCESS;
-                    } catch (RemoteException e) {
-                        foundParentInTask = false;
-                    }
-                    mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
-                            resultData, "navigate-up", true);
-                }
-            }
-            Binder.restoreCallingIdentity(origId);
-            return foundParentInTask;
+            return stack.navigateUpToLocked(srec, destIntent, resultCode, resultData);
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index cde17c9..c1b406e 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -22,6 +22,7 @@
 
 import android.app.Activity;
 import android.app.ActivityOptions;
+import android.app.ResultInfo;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -95,9 +96,9 @@
     ActivityRecord resultTo; // who started this entry, so will get our reply
     final String resultWho; // additional identifier for use by resultTo.
     final int requestCode;  // code given by requester (resultTo)
-    ArrayList results;      // pending ActivityResult objs we have received
+    ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
-    ArrayList newIntents;   // any pending new intents for single-top mode
+    ArrayList<Intent> newIntents; // any pending new intents for single-top mode
     ActivityOptions pendingOptions; // most recently given options
     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
     UriPermissionOwner uriPermissions; // current special URI access perms.
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d969709..76836f9 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -24,11 +24,13 @@
 import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
 import com.android.server.wm.AppTransition;
+import com.android.server.wm.TaskGroup;
 
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
+import android.app.IActivityController;
 import android.app.IActivityManager;
 import android.app.IThumbnailReceiver;
 import android.app.IThumbnailRetriever;
@@ -501,14 +503,10 @@
         return null;
     }
 
-    final int indexOfTokenLocked(IBinder token) {
+    private final int indexOfTokenLocked(IBinder token) {
         return mHistory.indexOf(ActivityRecord.forToken(token));
     }
 
-    final int indexOfActivityLocked(ActivityRecord r) {
-        return mHistory.indexOf(r);
-    }
-
     final ActivityRecord isInStackLocked(IBinder token) {
         ActivityRecord r = ActivityRecord.forToken(token);
         if (mHistory.contains(r)) {
@@ -517,14 +515,6 @@
         return null;
     }
 
-    // TODO: This exposes mHistory too much, replace usage with ActivityStack methods. 
-    final ActivityRecord getActivityAtIndex(int index) {
-        if (index >= 0 && index < mHistory.size()) {
-            return mHistory.get(index);
-        }
-        return null;
-    }
-
     int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
         TaskRecord lastTask = null;
         final int N = mHistory.size();
@@ -745,7 +735,13 @@
                 try {
                     profileFd = profileFd.dup();
                 } catch (IOException e) {
-                    profileFd = null;
+                    if (profileFd != null) {
+                        try {
+                            profileFd.close();
+                        } catch (IOException o) {
+                        }
+                        profileFd = null;
+                    }
                 }
             }
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
@@ -1758,7 +1754,7 @@
             
             try {
                 // Deliver all pending results.
-                ArrayList a = next.results;
+                ArrayList<ResultInfo> a = next.results;
                 if (a != null) {
                     final int N = a.size();
                     if (!next.finishing && N > 0) {
@@ -2156,6 +2152,7 @@
                             }
                             i++;
                         }
+                        mService.mWindowManager.moveTaskToBottom(target.task.taskId);
                         if (taskTop == p) {
                             taskTop = below;
                         }
@@ -2304,6 +2301,8 @@
                             validateAppTokensLocked();
                         }
                     }
+                    // TODO: This is wrong because it doesn't take lastReparentPos into account.
+                    mService.mWindowManager.moveTaskToTop(task.taskId);
                     replyChainEnd = -1;
                     
                     // Now we've moved it in to place...  but what if this is
@@ -2413,7 +2412,7 @@
                 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
                         && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
                     if (!ret.finishing) {
-                        int index = indexOfTokenLocked(ret.appToken);
+                        int index = mHistory.indexOf(ret);
                         if (index >= 0) {
                             finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
                                     null, "clear", false);
@@ -3568,7 +3567,7 @@
             }
 
             // Get the activity record.
-            int index = indexOfActivityLocked(r);
+            int index = mHistory.indexOf(r);
             if (index >= 0) {
                 res = r;
 
@@ -3654,7 +3653,7 @@
         // Stop any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (i=0; i<NS; i++) {
-            ActivityRecord r = (ActivityRecord)stops.get(i);
+            ActivityRecord r = stops.get(i);
             synchronized (mService) {
                 if (r.finishing) {
                     finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
@@ -3667,7 +3666,7 @@
         // Finish any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (i=0; i<NF; i++) {
-            ActivityRecord r = (ActivityRecord)finishes.get(i);
+            ActivityRecord r = finishes.get(i);
             synchronized (mService) {
                 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
             }
@@ -3675,7 +3674,7 @@
 
         // Report back to any thumbnail receivers.
         for (i=0; i<NT; i++) {
-            ActivityRecord r = (ActivityRecord)thumbnails.get(i);
+            ActivityRecord r = thumbnails.get(i);
             mService.sendPendingThumbnail(r, null, null, null, true);
         }
 
@@ -3730,7 +3729,7 @@
 
         int i;
         for (i=mHistory.size()-1; i>=0; i--) {
-            ActivityRecord r = (ActivityRecord)mHistory.get(i);
+            ActivityRecord r = mHistory.get(i);
             if (r.resultTo == self && r.requestCode == requestCode) {
                 if ((r.resultWho == null && resultWho == null) ||
                     (r.resultWho != null && r.resultWho.equals(resultWho))) {
@@ -3742,6 +3741,36 @@
         mService.updateOomAdjLocked();
     }
 
+    final void finishTopRunningActivityLocked(ProcessRecord app) {
+        ActivityRecord r = topRunningActivityLocked(null);
+        if (r != null && r.app == app) {
+            // If the top running activity is from this crashing
+            // process, then terminate it to avoid getting in a loop.
+            Slog.w(TAG, "  Force finishing activity "
+                    + r.intent.getComponent().flattenToShortString());
+            int index = mHistory.indexOf(r);
+            r.stack.finishActivityLocked(r, index,
+                    Activity.RESULT_CANCELED, null, "crashed", false);
+            // Also terminate any activities below it that aren't yet
+            // stopped, to avoid a situation where one will get
+            // re-start our crashing activity once it gets resumed again.
+            index--;
+            if (index >= 0) {
+                r = mHistory.get(index);
+                if (r.state == ActivityState.RESUMED
+                        || r.state == ActivityState.PAUSING
+                        || r.state == ActivityState.PAUSED) {
+                    if (!r.isHomeActivity || mService.mHomeProcess != r.app) {
+                        Slog.w(TAG, "  Force finishing activity "
+                                + r.intent.getComponent().flattenToShortString());
+                        r.stack.finishActivityLocked(r, index,
+                                Activity.RESULT_CANCELED, null, "crashed", false);
+                    }
+                }
+            }
+        }
+    }
+
     final boolean finishActivityAffinityLocked(IBinder token) {
         int index = indexOfTokenLocked(token);
         if (DEBUG_RESULTS) Slog.v(
@@ -3800,6 +3829,19 @@
      * @return Returns true if this activity has been removed from the history
      * list, or false if it is still in the list and will be removed later.
      */
+    final boolean finishActivityLocked(ActivityRecord r,
+            int resultCode, Intent resultData, String reason, boolean oomAdj) {
+        int index = mHistory.indexOf(r);
+        if (index >= 0) {
+            return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
+        }
+        return false;
+    }
+
+    /**
+     * @return Returns true if this activity has been removed from the history
+     * list, or false if it is still in the list and will be removed later.
+     */
     final boolean finishActivityLocked(ActivityRecord r, int index,
             int resultCode, Intent resultData, String reason, boolean oomAdj) {
         return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
@@ -3892,7 +3934,7 @@
 
     private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
             int mode, boolean oomAdj) {
-        final int index = indexOfActivityLocked(r);
+        final int index = mHistory.indexOf(r);
         if (index < 0) {
             return null;
         }
@@ -3948,16 +3990,102 @@
                 resumeTopActivityLocked(null);
             }
             return activityRemoved ? null : r;
-        } else {
-            // Need to go through the full pause cycle to get this
-            // activity into the stopped state and then finish it.
-            if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
-            mFinishingActivities.add(r);
-            resumeTopActivityLocked(null);
         }
+
+        // Need to go through the full pause cycle to get this
+        // activity into the stopped state and then finish it.
+        if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
+        mFinishingActivities.add(r);
+        resumeTopActivityLocked(null);
         return r;
     }
 
+    final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
+            Intent resultData) {
+        final int start = mHistory.indexOf(srec);
+        if (start < 0) {
+            // Current activity is not in history stack; do nothing.
+            return false;
+        }
+        int finishTo = start - 1;
+        ActivityRecord parent = null;
+        boolean foundParentInTask = false;
+        ComponentName dest = destIntent.getComponent();
+        if (dest != null) {
+            TaskRecord tr = srec.task;
+            for (int i = start - 1; i >= 0; i--) {
+                ActivityRecord r = mHistory.get(i);
+                if (tr != r.task) {
+                    // Couldn't find parent in the same task; stop at the one above this.
+                    // (Root of current task; in-app "home" behavior)
+                    // Always at least finish the current activity.
+                    finishTo = Math.min(start - 1, i + 1);
+                    parent = mHistory.get(finishTo);
+                    break;
+                } else if (r.info.packageName.equals(dest.getPackageName()) &&
+                        r.info.name.equals(dest.getClassName())) {
+                    finishTo = i;
+                    parent = r;
+                    foundParentInTask = true;
+                    break;
+                }
+            }
+        }
+
+        IActivityController controller = mService.mController;
+        if (controller != null) {
+            ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
+            if (next != null) {
+                // ask watcher if this is allowed
+                boolean resumeOK = true;
+                try {
+                    resumeOK = controller.activityResuming(next.packageName);
+                } catch (RemoteException e) {
+                    mService.mController = null;
+                }
+
+                if (!resumeOK) {
+                    return false;
+                }
+            }
+        }
+        final long origId = Binder.clearCallingIdentity();
+        for (int i = start; i > finishTo; i--) {
+            ActivityRecord r = mHistory.get(i);
+            requestFinishActivityLocked(r.appToken, resultCode, resultData,
+                    "navigate-up", true);
+            // Only return the supplied result for the first activity finished
+            resultCode = Activity.RESULT_CANCELED;
+            resultData = null;
+        }
+
+        if (parent != null && foundParentInTask) {
+            final int parentLaunchMode = parent.info.launchMode;
+            final int destIntentFlags = destIntent.getFlags();
+            if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
+                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
+                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
+                    (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
+                parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
+            } else {
+                try {
+                    ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
+                            destIntent.getComponent(), 0, srec.userId);
+                    int res = startActivityLocked(srec.app.thread, destIntent,
+                            null, aInfo, parent.appToken, null,
+                            0, -1, parent.launchedFromUid, parent.launchedFromPackage,
+                            0, null, true, null);
+                    foundParentInTask = res == ActivityManager.START_SUCCESS;
+                } catch (RemoteException e) {
+                    foundParentInTask = false;
+                }
+                requestFinishActivityLocked(parent.appToken, resultCode,
+                        resultData, "navigate-up", true);
+            }
+        }
+        Binder.restoreCallingIdentity(origId);
+        return foundParentInTask;
+    }
     /**
      * Perform the common clean-up of an activity record.  This is called both
      * as part of destroyActivityLocked() (when destroying the client-side
@@ -4216,7 +4344,7 @@
                     mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
                 }
 
-                int index = indexOfActivityLocked(r);
+                int index = mHistory.indexOf(r);
                 if (index >= 0) {
                     if (r.state == ActivityState.DESTROYING) {
                         cleanUpActivityLocked(r, true, false);
@@ -4230,15 +4358,15 @@
         }
     }
     
-    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app,
-            String listName) {
+    private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
+            ProcessRecord app, String listName) {
         int i = list.size();
         if (DEBUG_CLEANUP) Slog.v(
             TAG, "Removing app " + app + " from list " + listName
             + " with " + i + " entries");
         while (i > 0) {
             i--;
-            ActivityRecord r = (ActivityRecord)list.get(i);
+            ActivityRecord r = list.get(i);
             if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
             if (r.app == app) {
                 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
@@ -4264,7 +4392,7 @@
             TAG, "Removing app " + app + " from history with " + i + " entries");
         while (i > 0) {
             i--;
-            ActivityRecord r = (ActivityRecord)mHistory.get(i);
+            ActivityRecord r = mHistory.get(i);
             if (DEBUG_CLEANUP) Slog.v(
                 TAG, "Record #" + i + " " + r + ": app=" + r.app);
             if (r.app == app) {
@@ -4440,6 +4568,7 @@
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
         }
+        mService.mWindowManager.moveTaskToTop(task);
 
         finishTaskMoveLocked(task);
         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
@@ -4532,6 +4661,7 @@
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
         }
+        mService.mWindowManager.moveTaskToBottom(task);
 
         finishTaskMoveLocked(task);
         return true;
@@ -4561,9 +4691,8 @@
         TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
         if (info.numSubThumbbails <= 0) {
             return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
-        } else {
-            return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
         }
+        return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
     }
 
     public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
@@ -4643,6 +4772,7 @@
         }
         if (thumbs.numSubThumbbails > 0) {
             thumbs.retriever = new IThumbnailRetriever.Stub() {
+                @Override
                 public Bitmap getThumbnail(int index) {
                     if (index < 0 || index >= thumbs.subtasks.size()) {
                         return null;
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 5760dcd..18ccf75 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -547,6 +547,11 @@
                 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED);
         mUsers.put(0, primary);
         mNextSerialNumber = MIN_USER_ID;
+        
+        Bundle restrictions = new Bundle();
+        initRestrictionsToDefaults(restrictions);
+        mUserRestrictions.append(0, restrictions);
+        
         updateUserIdsLocked();
 
         writeUserListLocked();
@@ -805,6 +810,9 @@
                     userInfo.partial = false;
                     writeUserLocked(userInfo);
                     updateUserIdsLocked();
+                    Bundle restrictions = new Bundle();
+                    initRestrictionsToDefaults(restrictions);
+                    mUserRestrictions.append(userId, restrictions);
                 }
             }
             if (userInfo != null) {
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 906ea57..43a5f0c 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -16,12 +16,16 @@
 
 package com.android.server.wm;
 
+import android.os.Debug;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 class DisplayContentList extends ArrayList<DisplayContent> {
 }
@@ -34,7 +38,7 @@
  * WindowManagerService.mWindowMap.
  */
 class DisplayContent {
-//    private final static String TAG = "DisplayContent";
+    private final static String TAG = "DisplayContent";
 
     /** Unique identifier of this stack. */
     private final int mDisplayId;
@@ -97,7 +101,7 @@
     /**
      * Sorted most recent at top, oldest at [0].
      */
-//    ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
+    ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
     SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>();
 
     /**
@@ -133,24 +137,28 @@
     /**
      *  Find the location to insert a new AppWindowToken into the window-ordered app token list.
      * @param addPos The location the token was inserted into in mAppTokens.
-     * @param atoken The token to insert.
+     * @param wtoken The token to insert.
      */
-    void addAppToken(final int addPos, final AppWindowToken atoken) {
-        mAppTokens.add(addPos, atoken);
+    void addAppToken(final int addPos, final AppWindowToken wtoken) {
+        mAppTokens.add(addPos, wtoken);
 
         if (addPos == 0 || addPos == mAnimatingAppTokens.size()) {
             // It was inserted into the beginning or end of mAppTokens. Honor that.
-            mAnimatingAppTokens.add(addPos, atoken);
+            mAnimatingAppTokens.add(addPos, wtoken);
         } else {
             // Find the item immediately above the mAppTokens insertion point and put the token
             // immediately below that one in mAnimatingAppTokens.
             final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1);
-            mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), atoken);
+            mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken);
         }
 
-        TaskList task = mTaskIdToTaskList.get(atoken.groupId);
+        TaskList task = mTaskIdToTaskList.get(wtoken.groupId);
         if (task == null) {
-            mTaskIdToTaskList.put(atoken.groupId, new TaskList(atoken));
+            task = new TaskList(wtoken, this);
+            mTaskIdToTaskList.put(wtoken.groupId, task);
+            mTaskLists.add(task);
+        } else {
+            task.mAppTokens.add(wtoken);
         }
     }
 
@@ -163,6 +171,7 @@
             AppTokenList appTokens = task.mAppTokens;
             appTokens.remove(wtoken);
             if (appTokens.size() == 0) {
+                mTaskLists.remove(task);
                 mTaskIdToTaskList.delete(taskId);
             }
         }
@@ -186,7 +195,7 @@
 
         task = mTaskIdToTaskList.get(newTaskId);
         if (task == null) {
-            task = new TaskList(wtoken);
+            task = new TaskList(wtoken, this);
             mTaskIdToTaskList.put(newTaskId, task);
         } else {
             task.mAppTokens.add(wtoken);
@@ -195,6 +204,122 @@
         wtoken.groupId = newTaskId;
     }
 
+    class TaskListsIterator implements Iterator<TaskList> {
+        private int mCur;
+        private boolean mReverse;
+
+        TaskListsIterator() {
+            this(false);
+        }
+
+        TaskListsIterator(boolean reverse) {
+            mReverse = reverse;
+            int numTaskLists = mTaskLists.size();
+            mCur = reverse ? numTaskLists - 1 : 0;
+        }
+
+        @Override
+        public boolean hasNext() {
+            if (mReverse) {
+                return mCur >= 0;
+            }
+            return mCur < mTaskLists.size();
+        }
+
+        @Override
+        public TaskList next() {
+            if (hasNext()) {
+                TaskList taskList = mTaskLists.get(mCur);
+                mCur += (mReverse ? -1 : 1);
+                return taskList;
+            }
+            throw new NoSuchElementException();
+        }
+
+        @Override
+        public void remove() {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    class AppTokenIterator implements Iterator<AppWindowToken> {
+        final TaskListsIterator mIterator;
+        final boolean mReverse;
+        int mCur;
+        TaskList mTaskList;
+
+        public AppTokenIterator() {
+            this(false);
+        }
+
+        public AppTokenIterator(boolean reverse) {
+            mReverse = reverse;
+            mIterator = new TaskListsIterator(reverse);
+            getNextTaskList();
+        }
+
+        private void getNextTaskList() {
+            if (mIterator.hasNext()) {
+                mTaskList = mIterator.next();
+                mCur = mReverse ? mTaskList.mAppTokens.size() - 1 : 0;
+            }
+        }
+
+        @Override
+        public boolean hasNext() {
+            if (mTaskList == null) {
+                return false;
+            }
+            if (mReverse) {
+                return mCur >= 0;
+            }
+            return mCur < mTaskList.mAppTokens.size();
+        }
+
+        @Override
+        public AppWindowToken next() {
+            if (hasNext()) {
+                AppWindowToken wtoken = mTaskList.mAppTokens.get(mCur);
+                mCur += mReverse ? -1 : 1;
+                if (!hasNext()) {
+                    getNextTaskList();
+                }
+                return wtoken;
+            }
+            throw new NoSuchElementException();
+        }
+
+        @Override
+        public void remove() {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    void verifyAppTokens() {
+        AppTokenIterator iterator = new AppTokenIterator();
+        for (int i = 0; i < mAppTokens.size(); ++i) {
+            if (!iterator.hasNext()) {
+                Slog.e(TAG, "compareAppTokens: More mAppTokens than TaskList tokens. Callers="
+                        + Debug.getCallers(4));
+                while (i < mAppTokens.size()) {
+                    Slog.e(TAG, "compareAppTokens: mAppTokens[" + i + "]=" + mAppTokens.get(i));
+                    i++;
+                }
+                return;
+            }
+            AppWindowToken appToken = mAppTokens.get(i);
+            AppWindowToken taskListToken = iterator.next();
+            if (appToken != taskListToken) {
+                Slog.e(TAG, "compareAppTokens: Mismatch at " + i + " appToken=" + appToken
+                        + " taskListToken=" + taskListToken + ". Callers=" + Debug.getCallers(4));
+            }
+        }
+        if (iterator.hasNext()) {
+            Slog.e(TAG, "compareAppTokens: More TaskList tokens than mAppTokens Callers="
+                    + Debug.getCallers(4));
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
         final String subPrefix = "  " + prefix;
diff --git a/services/java/com/android/server/am/TaskGroup.java b/services/java/com/android/server/wm/TaskGroup.java
similarity index 96%
rename from services/java/com/android/server/am/TaskGroup.java
rename to services/java/com/android/server/wm/TaskGroup.java
index 7574103..5e82af2 100644
--- a/services/java/com/android/server/am/TaskGroup.java
+++ b/services/java/com/android/server/wm/TaskGroup.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.am;
+package com.android.server.wm;
 
 import android.view.IApplicationToken;
 
diff --git a/services/java/com/android/server/wm/TaskList.java b/services/java/com/android/server/wm/TaskList.java
index fe12b98..88791f2 100644
--- a/services/java/com/android/server/wm/TaskList.java
+++ b/services/java/com/android/server/wm/TaskList.java
@@ -16,15 +16,15 @@
 
 package com.android.server.wm;
 
-import com.android.server.am.TaskGroup;
-
-class TaskList extends TaskGroup {
+class TaskList {
 //    private final String TAG = "TaskGroup";
-    AppTokenList mAppTokens = new AppTokenList();
+    DisplayContent mDisplayContent;
+    final AppTokenList mAppTokens = new AppTokenList();
+    final int taskId;
 
-    TaskList(AppWindowToken wtoken) {
+    TaskList(AppWindowToken wtoken, DisplayContent displayContent) {
         taskId = wtoken.groupId;
-        tokens.add(wtoken.appToken);
         mAppTokens.add(wtoken);
+        mDisplayContent = displayContent;
     }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 62eccdf..d51c07b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -54,7 +54,6 @@
 import com.android.server.EventLogTags;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
-import com.android.server.am.TaskGroup;
 import com.android.server.display.DisplayManagerService;
 import com.android.server.input.InputManagerService;
 import com.android.server.power.PowerManagerService;
@@ -330,8 +329,7 @@
     /**
      * Mapping from a token IBinder to a WindowToken object.
      */
-    final HashMap<IBinder, WindowToken> mTokenMap =
-            new HashMap<IBinder, WindowToken>();
+    final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
 
     /**
      * List of window tokens that have finished starting their application,
@@ -746,6 +744,14 @@
         mActivityManager = ActivityManagerNative.getDefault();
         mBatteryStats = BatteryStatsService.getService();
         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
+        mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
+                new AppOpsManager.Callback() {
+                    @Override
+                    public void opChanged(int op, String packageName) {
+                        updateAppOpsState();
+                    }
+                }
+        );
 
         // Get persisted window scale setting
         mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
@@ -2150,7 +2156,10 @@
             win.attach();
             mWindowMap.put(client.asBinder(), win);
             if (win.mAppOp != AppOpsManager.OP_NONE) {
-                mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
+                if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
+                        != AppOpsManager.MODE_ALLOWED) {
+                    win.setAppOpVisibilityLw(false);
+                }
             }
 
             if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
@@ -2439,6 +2448,27 @@
         mInputMonitor.updateInputWindowsLw(true /*force*/);
     }
 
+    public void updateAppOpsState() {
+        synchronized(mWindowMap) {
+            boolean changed = false;
+            for (int i=0; i<mDisplayContents.size(); i++) {
+                DisplayContent display = mDisplayContents.valueAt(i);
+                WindowList windows = display.getWindowList();
+                for (int j=0; j<windows.size(); j++) {
+                    final WindowState win = windows.get(j);
+                    if (win.mAppOp != AppOpsManager.OP_NONE) {
+                        changed |= win.setAppOpVisibilityLw(mAppOps.checkOpNoThrow(win.mAppOp,
+                                win.getOwningUid(),
+                                win.getOwningPackage()) == AppOpsManager.MODE_ALLOWED);
+                    }
+                }
+            }
+            if (changed) {
+                scheduleAnimationLocked();
+            }
+        }
+    }
+
     static void logSurface(WindowState w, String msg, RuntimeException where) {
         String str = "  SURFACE " + msg + ": " + w;
         if (where != null) {
@@ -3286,6 +3316,7 @@
                 mTaskIdToDisplayContents.put(taskId, displayContent);
             }
             displayContent.addAppToken(addPos, atoken);
+            displayContent.verifyAppTokens();
             mTokenMap.put(token.asBinder(), atoken);
             mTaskIdToDisplayContents.put(taskId, displayContent);
 
@@ -4269,11 +4300,12 @@
                         TAG, "Removing app " + wtoken + " delayed=" + delayed
                         + " animation=" + wtoken.mAppAnimator.animation
                         + " animating=" + wtoken.mAppAnimator.animating);
+                DisplayContent displayContent = mTaskIdToDisplayContents.get(wtoken.groupId);
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                             "removeAppToken make exiting: " + wtoken);
-                    mTaskIdToDisplayContents.get(wtoken.groupId).mExitingAppTokens.add(wtoken);
+                    displayContent.mExitingAppTokens.add(wtoken);
                 } else {
                     // Make sure there is no animation running on this token,
                     // so any windows associated with it will be removed as
@@ -4283,7 +4315,8 @@
                 }
                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                         "removeAppToken: " + wtoken);
-                mTaskIdToDisplayContents.get(wtoken.groupId).removeAppToken(wtoken);
+                displayContent.removeAppToken(wtoken);
+                displayContent.verifyAppTokens();
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
                     startingToken = wtoken;
@@ -4675,6 +4708,44 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    public void moveTaskToTop(int taskId) {
+        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
+        if (displayContent == null) {
+            Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
+                    + " not found in mTaskIdToDisplayContents");
+            return;
+        }
+        TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
+        if (taskList == null) {
+            Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskIdToTaskLists");
+            return;
+        }
+        if (!displayContent.mTaskLists.remove(taskList)) {
+            Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskLists");
+        }
+        displayContent.mTaskLists.add(taskList);
+        displayContent.verifyAppTokens();
+    }
+
+    public void moveTaskToBottom(int taskId) {
+        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
+        if (displayContent == null) {
+            Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
+                    + " not found in mTaskIdToDisplayContents");
+            return;
+        }
+        TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
+        if (taskList == null) {
+            Slog.e(TAG, "moveTaskToTopBottomtaskId=" + taskId + " not found in mTaskIdToTaskLists");
+            return;
+        }
+        if (!displayContent.mTaskLists.remove(taskList)) {
+            Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTaskLists");
+        }
+        displayContent.mTaskLists.add(0, taskList);
+        displayContent.verifyAppTokens();
+    }
+
     // -------------------------------------------------------------
     // Misc IWindowSession methods
     // -------------------------------------------------------------
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 6648e56..8dda544 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -96,6 +96,7 @@
     int mSystemUiVisibility;
     boolean mPolicyVisibility = true;
     boolean mPolicyVisibilityAfterAnim = true;
+    boolean mAppOpVisibility = true;
     boolean mAppFreezing;
     boolean mAttachedHidden;    // is our parent window hidden?
     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
@@ -982,6 +983,10 @@
                     + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid);
             return false;
         }
+        if (!mAppOpVisibility) {
+            // Being hidden due to app op request.
+            return false;
+        }
         if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
             // Already showing.
             return false;
@@ -1053,6 +1058,25 @@
         return true;
     }
 
+    public boolean setAppOpVisibilityLw(boolean state) {
+        if (mAppOpVisibility != state) {
+            mAppOpVisibility = state;
+            if (state) {
+                // If the policy visibility had last been to hide, then this
+                // will incorrectly show at this point since we lost that
+                // information.  Not a big deal -- for the windows that have app
+                // ops modifies they should only be hidden by policy due to the
+                // lock screen, and the user won't be changing this if locked.
+                // Plus it will quickly be fixed the next time we do a layout.
+                showLw(true, false);
+            } else {
+                hideLw(true, false);
+            }
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public boolean isAlive() {
         return mClient.asBinder().isBinderAlive();
@@ -1179,11 +1203,14 @@
             pw.print(" mSystemUiVisibility=0x");
             pw.println(Integer.toHexString(mSystemUiVisibility));
         }
-        if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
+        if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
+                || mAttachedHidden) {
             pw.print(prefix); pw.print("mPolicyVisibility=");
                     pw.print(mPolicyVisibility);
                     pw.print(" mPolicyVisibilityAfterAnim=");
                     pw.print(mPolicyVisibilityAfterAnim);
+                    pw.print(" mAppOpVisibility=");
+                    pw.print(mAppOpVisibility);
                     pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
         }
         if (!mRelayoutCalled || mLayoutNeeded) {
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 35dea24..d7a58b6 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -26,7 +26,7 @@
 public final class CellInfoLte extends CellInfo implements Parcelable {
 
     private static final String LOG_TAG = "CellInfoLte";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private CellIdentityLte mCellIdentityLte;
     private CellSignalStrengthLte mCellSignalStrengthLte;
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
index ddc6a99..3af3745 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
@@ -39,6 +39,7 @@
         typeBuilder.setX(X).setY(Y);
         Allocation A = Allocation.createTyped(RS, typeBuilder.create());
         s.bind_a(A);
+        s.set_aRaw(A);
 
         typeBuilder = new Type.Builder(RS, Element.I32(RS));
         typeBuilder.setX(X).setY(Y).setFaces(true);
@@ -59,6 +60,7 @@
         ScriptC_alloc s = new ScriptC_alloc(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
+        s.forEach_root(s.get_aRaw());
         s.invoke_alloc_test();
         pRS.finish();
         waitForMessage();
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
index c3f3ca0..fd18f93 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
@@ -37,7 +37,7 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         A = Allocation.createTyped(RS, typeBuilder.create());
-        s.bind_a(A);
+        s.set_aRaw(A);
 
         return;
     }
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
index 653ebd5..13fefe7 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
@@ -37,7 +37,7 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         A = Allocation.createTyped(RS, typeBuilder.create());
-        s.bind_a(A);
+        s.set_aRaw(A);
         s.set_s(s);
         s.set_ain(A);
         s.set_aout(A);
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
index 69fc97f..606af4d 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
@@ -37,7 +37,7 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         A = Allocation.createTyped(RS, typeBuilder.create());
-        s.bind_a(A);
+        s.set_aRaw(A);
 
         return;
     }
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
index 3116e5a..1b5e2ac 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
@@ -5,39 +5,37 @@
 int dimY;
 int dimZ;
 
+rs_allocation aRaw;
 rs_allocation aFaces;
 rs_allocation aLOD;
 rs_allocation aFacesLOD;
 
+void root(int *o, uint32_t x, uint32_t y) {
+    *o = x + y * dimX;
+}
+
 static bool test_alloc_dims() {
     bool failed = false;
     int i, j;
 
-    for (j = 0; j < dimY; j++) {
-        for (i = 0; i < dimX; i++) {
-            a[i + j * dimX] = i + j * dimX;
-        }
-    }
-
-    rs_allocation alloc = rsGetAllocation(a);
-    _RS_ASSERT(rsAllocationGetDimX(alloc) == dimX);
-    _RS_ASSERT(rsAllocationGetDimY(alloc) == dimY);
-    _RS_ASSERT(rsAllocationGetDimZ(alloc) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimX(aRaw) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aRaw) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aRaw) == dimZ);
 
     // Test 2D addressing
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
             rsDebug("Verifying ", i + j * dimX);
-            const void *p = rsGetElementAt(alloc, i, j);
+            const void *p = rsGetElementAt(aRaw, i, j);
             int val = *(const int *)p;
             _RS_ASSERT(val == (i + j * dimX));
         }
     }
 
     // Test 1D addressing
-    for (i = 0; i < dimX * dimY; i++) {
+    for (i = 0; i < dimX; i++) {
         rsDebug("Verifying ", i);
-        const void *p = rsGetElementAt(alloc, i);
+        const void *p = rsGetElementAt(aRaw, i);
         int val = *(const int *)p;
         _RS_ASSERT(val == i);
     }
@@ -46,7 +44,7 @@
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
             rsDebug("Verifying ", i + j * dimX);
-            const void *p = rsGetElementAt(alloc, i, j, 0);
+            const void *p = rsGetElementAt(aRaw, i, j, 0);
             int val = *(const int *)p;
             _RS_ASSERT(val == (i + j * dimX));
         }
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
index ac527b5..08e6bed 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
@@ -1,6 +1,6 @@
 #include "shared.rsh"
 
-int *a;
+rs_allocation aRaw;
 int dimX;
 int dimY;
 static bool failed = false;
@@ -21,7 +21,8 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
-            _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (i + j * dimX));
         }
     }
 
@@ -41,7 +42,8 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
-            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
         }
     }
 
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
index ddf17f8..89df090 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
@@ -1,6 +1,5 @@
 #include "shared.rsh"
 
-int *a;
 int dimX;
 int dimY;
 int xStart = 0;
@@ -9,6 +8,7 @@
 int yEnd = 0;
 
 rs_script s;
+rs_allocation aRaw;
 rs_allocation ain;
 rs_allocation aout;
 
@@ -26,13 +26,14 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
             rsDebug("i: ", i);
             rsDebug("j: ", j);
-            rsDebug("a[j][i]: ", a[i + j * dimX]);
+            rsDebug("a[j][i]: ", v);
             if (i < xStart || i >= xEnd || j < yStart || j >= yEnd) {
-                _RS_ASSERT(a[i + j * dimX] == 0);
+                _RS_ASSERT(v == 0);
             } else {
-                _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+                _RS_ASSERT(v == (i + j * dimX));
             }
         }
     }
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
index 33944aa..2c807bd 100644
--- a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
@@ -1,6 +1,6 @@
 #include "shared.rsh"
 
-int *a;
+rs_allocation aRaw;
 int dimX;
 int dimY;
 static bool failed = false;
@@ -15,7 +15,8 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
-            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
         }
     }
 
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java
index a06d820..3ea942c 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_alloc.java
@@ -39,6 +39,7 @@
         typeBuilder.setX(X).setY(Y);
         Allocation A = Allocation.createTyped(RS, typeBuilder.create());
         s.bind_a(A);
+        s.set_aRaw(A);
 
         typeBuilder = new Type.Builder(RS, Element.I32(RS));
         typeBuilder.setX(X).setY(Y).setFaces(true);
@@ -59,6 +60,7 @@
         ScriptC_alloc s = new ScriptC_alloc(pRS);
         pRS.setMessageHandler(mRsMessage);
         initializeGlobals(pRS, s);
+        s.forEach_root(s.get_aRaw());
         s.invoke_alloc_test();
         pRS.finish();
         waitForMessage();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java
index 4951970..6c95109 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach.java
@@ -37,7 +37,7 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         A = Allocation.createTyped(RS, typeBuilder.create());
-        s.bind_a(A);
+        s.set_aRaw(A);
 
         return;
     }
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach_bounds.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach_bounds.java
index bda055b..782f788 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach_bounds.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_foreach_bounds.java
@@ -37,7 +37,7 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         A = Allocation.createTyped(RS, typeBuilder.create());
-        s.bind_a(A);
+        s.set_aRaw(A);
         s.set_s(s);
         s.set_ain(A);
         s.set_aout(A);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java
index cc48591..69526a8 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_noroot.java
@@ -37,7 +37,7 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         A = Allocation.createTyped(RS, typeBuilder.create());
-        s.bind_a(A);
+        s.set_aRaw(A);
 
         return;
     }
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/alloc.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/alloc.rs
index 3116e5a..1b5e2ac 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/alloc.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/alloc.rs
@@ -5,39 +5,37 @@
 int dimY;
 int dimZ;
 
+rs_allocation aRaw;
 rs_allocation aFaces;
 rs_allocation aLOD;
 rs_allocation aFacesLOD;
 
+void root(int *o, uint32_t x, uint32_t y) {
+    *o = x + y * dimX;
+}
+
 static bool test_alloc_dims() {
     bool failed = false;
     int i, j;
 
-    for (j = 0; j < dimY; j++) {
-        for (i = 0; i < dimX; i++) {
-            a[i + j * dimX] = i + j * dimX;
-        }
-    }
-
-    rs_allocation alloc = rsGetAllocation(a);
-    _RS_ASSERT(rsAllocationGetDimX(alloc) == dimX);
-    _RS_ASSERT(rsAllocationGetDimY(alloc) == dimY);
-    _RS_ASSERT(rsAllocationGetDimZ(alloc) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimX(aRaw) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aRaw) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aRaw) == dimZ);
 
     // Test 2D addressing
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
             rsDebug("Verifying ", i + j * dimX);
-            const void *p = rsGetElementAt(alloc, i, j);
+            const void *p = rsGetElementAt(aRaw, i, j);
             int val = *(const int *)p;
             _RS_ASSERT(val == (i + j * dimX));
         }
     }
 
     // Test 1D addressing
-    for (i = 0; i < dimX * dimY; i++) {
+    for (i = 0; i < dimX; i++) {
         rsDebug("Verifying ", i);
-        const void *p = rsGetElementAt(alloc, i);
+        const void *p = rsGetElementAt(aRaw, i);
         int val = *(const int *)p;
         _RS_ASSERT(val == i);
     }
@@ -46,7 +44,7 @@
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
             rsDebug("Verifying ", i + j * dimX);
-            const void *p = rsGetElementAt(alloc, i, j, 0);
+            const void *p = rsGetElementAt(aRaw, i, j, 0);
             int val = *(const int *)p;
             _RS_ASSERT(val == (i + j * dimX));
         }
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach.rs
index ac527b5..08e6bed 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach.rs
@@ -1,6 +1,6 @@
 #include "shared.rsh"
 
-int *a;
+rs_allocation aRaw;
 int dimX;
 int dimY;
 static bool failed = false;
@@ -21,7 +21,8 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
-            _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (i + j * dimX));
         }
     }
 
@@ -41,7 +42,8 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
-            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
         }
     }
 
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach_bounds.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach_bounds.rs
index ddf17f8..89df090 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach_bounds.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/foreach_bounds.rs
@@ -1,6 +1,5 @@
 #include "shared.rsh"
 
-int *a;
 int dimX;
 int dimY;
 int xStart = 0;
@@ -9,6 +8,7 @@
 int yEnd = 0;
 
 rs_script s;
+rs_allocation aRaw;
 rs_allocation ain;
 rs_allocation aout;
 
@@ -26,13 +26,14 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
             rsDebug("i: ", i);
             rsDebug("j: ", j);
-            rsDebug("a[j][i]: ", a[i + j * dimX]);
+            rsDebug("a[j][i]: ", v);
             if (i < xStart || i >= xEnd || j < yStart || j >= yEnd) {
-                _RS_ASSERT(a[i + j * dimX] == 0);
+                _RS_ASSERT(v == 0);
             } else {
-                _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+                _RS_ASSERT(v == (i + j * dimX));
             }
         }
     }
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/noroot.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/noroot.rs
index 33944aa..2c807bd 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/noroot.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/noroot.rs
@@ -1,6 +1,6 @@
 #include "shared.rsh"
 
-int *a;
+rs_allocation aRaw;
 int dimX;
 int dimY;
 static bool failed = false;
@@ -15,7 +15,8 @@
 
     for (j = 0; j < dimY; j++) {
         for (i = 0; i < dimX; i++) {
-            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
         }
     }
 
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 5b71adc..2149190 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1185,6 +1185,11 @@
         return true;
     }
 
+    if (strcmp(name, "xxxhdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_XXXHIGH;
+        return true;
+    }
+
     char* c = (char*)name;
     while (*c >= '0' && *c <= '9') {
         c++;
diff --git a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java
new file mode 100644
index 0000000..8cd1a69
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.format;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.Context;
+
+
+/**
+ * Delegate used to provide new implementation for the native methods of {@link DateFormat}
+ *
+ * Through the layoutlib_create tool, the original  methods of DateFormat have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class DateFormat_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static boolean is24HourFormat(Context context) {
+        return false;
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 80a1a60..d955040 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -110,6 +110,7 @@
         "android.os.Handler#sendMessageAtTime",
         "android.os.HandlerThread#run",
         "android.os.Build#getString",
+        "android.text.format.DateFormat#is24HourFormat",
         "android.view.Choreographer#getRefreshRate",
         "android.view.Display#updateDisplayInfoLocked",
         "android.view.LayoutInflater#rInflate",
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 66c2f3f..eb2f74c 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -35,6 +35,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.UserHandle;
+import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -144,6 +145,7 @@
     private static final String EOS = "eos";
 
     private WifiNative mWifiNative;
+    private final KeyStore mKeyStore = KeyStore.getInstance();
 
     WifiConfigStore(Context c, WifiNative wn) {
         mContext = c;
@@ -295,16 +297,7 @@
     boolean forgetNetwork(int netId) {
         if (mWifiNative.removeNetwork(netId)) {
             mWifiNative.saveConfig();
-            WifiConfiguration target = null;
-            WifiConfiguration config = mConfiguredNetworks.get(netId);
-            if (config != null) {
-                target = mConfiguredNetworks.remove(netId);
-                mNetworkIds.remove(configKey(config));
-            }
-            if (target != null) {
-                writeIpAndProxyConfigurations();
-                sendConfiguredNetworksChangedBroadcast(target, WifiManager.CHANGE_REASON_REMOVED);
-            }
+            removeConfigAndSendBroadcastIfNeeded(netId);
             return true;
         } else {
             loge("Failed to remove network " + netId);
@@ -342,20 +335,27 @@
      */
     boolean removeNetwork(int netId) {
         boolean ret = mWifiNative.removeNetwork(netId);
-        WifiConfiguration config = null;
         if (ret) {
-            config = mConfiguredNetworks.get(netId);
-            if (config != null) {
-                config = mConfiguredNetworks.remove(netId);
-                mNetworkIds.remove(configKey(config));
-            }
-        }
-        if (config != null) {
-            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
+            removeConfigAndSendBroadcastIfNeeded(netId);
         }
         return ret;
     }
 
+    private void removeConfigAndSendBroadcastIfNeeded(int netId) {
+        WifiConfiguration config = mConfiguredNetworks.get(netId);
+        if (config != null) {
+            // Remove any associated keys
+            if (config.enterpriseConfig != null) {
+                config.enterpriseConfig.removeKeys(mKeyStore);
+            }
+            mConfiguredNetworks.remove(netId);
+            mNetworkIds.remove(configKey(config));
+
+            writeIpAndProxyConfigurations();
+            sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
+        }
+    }
+
     /**
      * Enable a network. Note that there is no saveConfig operation.
      * This function is retained for compatibility with the public
@@ -1090,13 +1090,48 @@
             }
 
             if (config.enterpriseConfig != null) {
-                HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
+
+                WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
+
+                if (enterpriseConfig.needsKeyStore()) {
+                    /**
+                     * Keyguard settings may eventually be controlled by device policy.
+                     * We check here if keystore is unlocked before installing
+                     * credentials.
+                     * TODO: Figure a way to store these credentials for wifi alone
+                     * TODO: Do we need a dialog here ?
+                     */
+                    if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
+                        loge(config.SSID + ": key store is locked");
+                        break setVariables;
+                    }
+
+                    try {
+                        /* config passed may include only fields being updated.
+                         * In order to generate the key id, fetch uninitialized
+                         * fields from the currently tracked configuration
+                         */
+                        WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
+                        String keyId = config.getKeyIdForCredentials(currentConfig);
+
+                        if (!enterpriseConfig.installKeys(mKeyStore, keyId)) {
+                            loge(config.SSID + ": failed to install keys");
+                            break setVariables;
+                        }
+                    } catch (IllegalStateException e) {
+                        loge(config.SSID + " invalid config for key installation");
+                        break setVariables;
+                    }
+                }
+
+                HashMap<String, String> enterpriseFields = enterpriseConfig.getFields();
                 for (String key : enterpriseFields.keySet()) {
                         String value = enterpriseFields.get(key);
                         if (!mWifiNative.setNetworkVariable(
                                     netId,
                                     key,
                                     value)) {
+                            enterpriseConfig.removeKeys(mKeyStore);
                             loge(config.SSID + ": failed to set " + key +
                                     ": " + value);
                             break setVariables;
@@ -1104,7 +1139,7 @@
                 }
             }
             updateFailed = false;
-        }
+        } //end of setVariables
 
         if (updateFailed) {
             if (newNetwork) {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 552356c..bf82792 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -19,6 +19,7 @@
 import android.net.LinkProperties;
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.text.TextUtils;
 
 import java.util.BitSet;
 
@@ -274,7 +275,8 @@
      */
     public BitSet allowedGroupCiphers;
     /**
-     * The enterprise configuration details
+     * The enterprise configuration details specifying the EAP method,
+     * certificates and other settings associated with the EAP.
      * @hide
      */
     public WifiEnterpriseConfig enterpriseConfig;
@@ -462,6 +464,47 @@
         return SSID;
     }
 
+    /**
+     * Get an identifier for associating credentials with this config
+     * @param current configuration contains values for additional fields
+     *                that are not part of this configuration. Used
+     *                when a config with some fields is passed by an application.
+     * @throws IllegalStateException if config is invalid for key id generation
+     * @hide
+     */
+    String getKeyIdForCredentials(WifiConfiguration current) {
+        String keyMgmt = null;
+
+        try {
+            // Get current config details for fields that are not initialized
+            if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
+            if (allowedKeyManagement.cardinality() == 0) {
+                allowedKeyManagement = current.allowedKeyManagement;
+            }
+            if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
+                keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP];
+            }
+            if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+                keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
+            }
+
+            if (TextUtils.isEmpty(keyMgmt)) {
+                throw new IllegalStateException("Not an EAP network");
+            }
+
+            return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" +
+                    trimStringForKeyId(enterpriseConfig.getKeyId(current != null ?
+                            current.enterpriseConfig : null));
+        } catch (NullPointerException e) {
+            throw new IllegalStateException("Invalid config details");
+        }
+    }
+
+    private String trimStringForKeyId(String string) {
+        // Remove quotes and spaces
+        return string.replace("\"", "").replace(" ", "");
+    }
+
     private static BitSet readBitSet(Parcel src) {
         int cardinality = src.readInt();
 
@@ -485,6 +528,9 @@
 
     /** @hide */
     public int getAuthType() {
+        if (allowedKeyManagement.cardinality() > 1) {
+            throw new IllegalStateException("More than one auth type set");
+        }
         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
             return KeyMgmt.WPA_PSK;
         } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 4dca7ac..7313e7e 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -19,7 +19,26 @@
 import android.os.Parcelable;
 import android.security.Credentials;
 import android.text.TextUtils;
+import android.util.Log;
 
+import com.android.org.bouncycastle.asn1.ASN1InputStream;
+import com.android.org.bouncycastle.asn1.ASN1Sequence;
+import com.android.org.bouncycastle.asn1.DEROctetString;
+import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -70,6 +89,9 @@
     private static final String PRIVATE_KEY_ID_KEY  = "key_id";
 
     private HashMap<String, String> mFields = new HashMap<String, String>();
+    private X509Certificate mCaCert;
+    private PrivateKey mClientPrivateKey;
+    private X509Certificate mClientCertificate;
 
     /** This represents an empty value of an enterprise field.
      * NULL is used at wpa_supplicant to indicate an empty value
@@ -103,6 +125,34 @@
             dest.writeString(entry.getKey());
             dest.writeString(entry.getValue());
         }
+
+        writeCertificate(dest, mCaCert);
+
+        if (mClientPrivateKey != null) {
+            String algorithm = mClientPrivateKey.getAlgorithm();
+            byte[] userKeyBytes = mClientPrivateKey.getEncoded();
+            dest.writeInt(userKeyBytes.length);
+            dest.writeByteArray(userKeyBytes);
+            dest.writeString(algorithm);
+        } else {
+            dest.writeInt(0);
+        }
+
+        writeCertificate(dest, mClientCertificate);
+    }
+
+    private void writeCertificate(Parcel dest, X509Certificate cert) {
+        if (cert != null) {
+            try {
+                byte[] certBytes = cert.getEncoded();
+                dest.writeInt(certBytes.length);
+                dest.writeByteArray(certBytes);
+            } catch (CertificateEncodingException e) {
+                dest.writeInt(0);
+            }
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     public static final Creator<WifiEnterpriseConfig> CREATOR =
@@ -115,9 +165,47 @@
                         String value = in.readString();
                         enterpriseConfig.mFields.put(key, value);
                     }
+
+                    enterpriseConfig.mCaCert = readCertificate(in);
+
+                    PrivateKey userKey = null;
+                    int len = in.readInt();
+                    if (len > 0) {
+                        try {
+                            byte[] bytes = new byte[len];
+                            in.readByteArray(bytes);
+                            String algorithm = in.readString();
+                            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+                            userKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes));
+                        } catch (NoSuchAlgorithmException e) {
+                            userKey = null;
+                        } catch (InvalidKeySpecException e) {
+                            userKey = null;
+                        }
+                    }
+
+                    enterpriseConfig.mClientPrivateKey = userKey;
+                    enterpriseConfig.mClientCertificate = readCertificate(in);
                     return enterpriseConfig;
                 }
 
+                private X509Certificate readCertificate(Parcel in) {
+                    X509Certificate cert = null;
+                    int len = in.readInt();
+                    if (len > 0) {
+                        try {
+                            byte[] bytes = new byte[len];
+                            in.readByteArray(bytes);
+                            CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
+                            cert = (X509Certificate) cFactory
+                                    .generateCertificate(new ByteArrayInputStream(bytes));
+                        } catch (CertificateException e) {
+                            cert = null;
+                        }
+                    }
+                    return cert;
+                }
+
                 public WifiEnterpriseConfig[] newArray(int size) {
                     return new WifiEnterpriseConfig[size];
                 }
@@ -145,13 +233,13 @@
         public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP", "MSCHAPV2", "GTC" };
     }
 
-    /** Internal use only @hide */
-    public HashMap<String, String> getFields() {
+    /** Internal use only */
+    HashMap<String, String> getFields() {
         return mFields;
     }
 
-    /** Internal use only @hide */
-    public static String[] getSupplicantKeys() {
+    /** Internal use only */
+    static String[] getSupplicantKeys() {
         return new String[] { EAP_KEY, PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY, PASSWORD_KEY,
                 CLIENT_CERT_KEY, CA_CERT_KEY, SUBJECT_MATCH_KEY, ENGINE_KEY, ENGINE_ID_KEY,
                 PRIVATE_KEY_ID_KEY };
@@ -271,28 +359,47 @@
      * a certificate
      * </p>
      * @param alias identifies the certificate
+     * @hide
      */
-    public void setCaCertificate(String alias) {
+    public void setCaCertificateAlias(String alias) {
         setFieldValue(CA_CERT_KEY, alias, CA_CERT_PREFIX);
     }
 
     /**
      * Get CA certificate alias
      * @return alias to the CA certificate
+     * @hide
      */
-    public String getCaCertificate() {
+    public String getCaCertificateAlias() {
         return getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
     }
 
     /**
+     * Specify a X.509 certificate that identifies the server.
+     *
+     * <p>A default name is automatically assigned to the certificate and used
+     * with this configuration.
+     * @param cert X.509 CA certificate
+     * @throws IllegalArgumentException if not a CA certificate
+     */
+    public void setCaCertificate(X509Certificate cert) {
+        if (cert.getBasicConstraints() >= 0) {
+            mCaCert = cert;
+        } else {
+            throw new IllegalArgumentException("Not a CA certificate");
+        }
+    }
+
+    /**
      * Set Client certificate alias.
      *
      * <p> See the {@link android.security.KeyChain} for details on installing or choosing
      * a certificate
      * </p>
      * @param alias identifies the certificate
+     * @hide
      */
-    public void setClientCertificate(String alias) {
+    public void setClientCertificateAlias(String alias) {
         setFieldValue(CLIENT_CERT_KEY, alias, CLIENT_CERT_PREFIX);
         setFieldValue(PRIVATE_KEY_ID_KEY, alias, Credentials.USER_PRIVATE_KEY);
         // Also, set engine parameters
@@ -308,12 +415,118 @@
     /**
      * Get client certificate alias
      * @return alias to the client certificate
+     * @hide
      */
-    public String getClientCertificate() {
+    public String getClientCertificateAlias() {
         return getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
     }
 
     /**
+     * Specify a private key and client certificate for client authorization.
+     *
+     * <p>A default name is automatically assigned to the key entry and used
+     * with this configuration.
+     * @param privateKey
+     * @param clientCertificate
+     */
+    public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) {
+        if (clientCertificate != null) {
+            if (clientCertificate.getBasicConstraints() != -1) {
+                throw new IllegalArgumentException("Cannot be a CA certificate");
+            }
+            if (privateKey == null) {
+                throw new IllegalArgumentException("Client cert without a private key");
+            }
+            if (privateKey.getEncoded() == null) {
+                throw new IllegalArgumentException("Private key cannot be encoded");
+            }
+        }
+
+        mClientPrivateKey = privateKey;
+        mClientCertificate = clientCertificate;
+    }
+
+    boolean needsKeyStore() {
+        // Has no keys to be installed
+        if (mClientCertificate == null && mCaCert == null) return false;
+        return true;
+    }
+
+    boolean installKeys(android.security.KeyStore keyStore, String name) {
+        boolean ret = true;
+        String privKeyName = Credentials.USER_PRIVATE_KEY + name;
+        String userCertName = Credentials.USER_CERTIFICATE + name;
+        String caCertName = Credentials.CA_CERTIFICATE + name;
+        if (mClientCertificate != null) {
+            byte[] privKeyData = mClientPrivateKey.getEncoded();
+            ret = keyStore.importKey(privKeyName, privKeyData);
+            if (ret == false) {
+                return ret;
+            }
+
+            ret = putCertInKeyStore(keyStore, userCertName, mClientCertificate);
+            if (ret == false) {
+                // Remove private key installed
+                keyStore.delKey(privKeyName);
+                return ret;
+            }
+        }
+
+        if (mCaCert != null) {
+            ret = putCertInKeyStore(keyStore, caCertName, mCaCert);
+            if (ret == false) {
+                if (mClientCertificate != null) {
+                    // Remove client key+cert
+                    keyStore.delKey(privKeyName);
+                    keyStore.delete(userCertName);
+                }
+                return ret;
+            }
+        }
+
+        // Set alias names
+        if (mClientCertificate != null) {
+            setClientCertificateAlias(name);
+            mClientPrivateKey = null;
+            mClientCertificate = null;
+        }
+
+        if (mCaCert != null) {
+            setCaCertificateAlias(name);
+            mCaCert = null;
+        }
+
+        return ret;
+    }
+
+    private boolean putCertInKeyStore(android.security.KeyStore keyStore, String name,
+            Certificate cert) {
+        try {
+            byte[] certData = Credentials.convertToPem(cert);
+            return keyStore.put(name, certData);
+        } catch (IOException e1) {
+            return false;
+        } catch (CertificateException e2) {
+            return false;
+        }
+    }
+
+    void removeKeys(android.security.KeyStore keyStore) {
+        String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
+        // a valid client certificate is configured
+        if (!TextUtils.isEmpty(client)) {
+            keyStore.delKey(Credentials.USER_PRIVATE_KEY + client);
+            keyStore.delete(Credentials.USER_CERTIFICATE + client);
+        }
+
+        String ca = getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
+        // a valid ca certificate is configured
+        if (!TextUtils.isEmpty(ca)) {
+            keyStore.delete(Credentials.CA_CERTIFICATE + ca);
+        }
+    }
+
+    /**
      * Set subject match. This is the substring to be matched against the subject of the
      * authentication server certificate.
      * @param subjectMatch substring to be matched
@@ -330,13 +543,28 @@
         return getFieldValue(SUBJECT_MATCH_KEY, "");
     }
 
+    /** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */
+    String getKeyId(WifiEnterpriseConfig current) {
+        String eap = mFields.get(EAP_KEY);
+        String phase2 = mFields.get(PHASE2_KEY);
+
+        // If either eap or phase2 are not initialized, use current config details
+        if (TextUtils.isEmpty((eap))) {
+            eap = current.mFields.get(EAP_KEY);
+        }
+        if (TextUtils.isEmpty(phase2)) {
+            phase2 = current.mFields.get(PHASE2_KEY);
+        }
+        return eap + "_" + phase2;
+    }
+
     /** Migrates the old style TLS config to the new config style. This should only be used
      * when restoring an old wpa_supplicant.conf or upgrading from a previous
      * platform version.
      * @return true if the config was updated
      * @hide
      */
-    public boolean migrateOldEapTlsNative(WifiNative wifiNative, int netId) {
+    boolean migrateOldEapTlsNative(WifiNative wifiNative, int netId) {
         String oldPrivateKey = wifiNative.getNetworkVariable(netId, OLD_PRIVATE_KEY_NAME);
         /*
          * If the old configuration value is not present, then there is nothing
@@ -395,6 +623,7 @@
      * @return the index into array
      */
     private int getStringIndex(String arr[], String toBeFound, int defaultIndex) {
+        if (TextUtils.isEmpty(toBeFound)) return defaultIndex;
         for (int i = 0; i < arr.length; i++) {
             if (toBeFound.equals(arr[i])) return i;
         }
@@ -408,7 +637,8 @@
      */
     private String getFieldValue(String key, String prefix) {
         String value = mFields.get(key);
-        if (EMPTY_VALUE.equals(value)) return "";
+        // Uninitialized or known to be empty after reading from supplicant
+        if (TextUtils.isEmpty(value) || EMPTY_VALUE.equals(value)) return "";
         return removeDoubleQuotes(value).substring(prefix.length());
     }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 77604a4..1589fec 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1332,10 +1332,19 @@
                                 P2pStateMachine.this, mGroup.getInterface());
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
                         WifiP2pDevice groupOwner = mGroup.getOwner();
-                        /* update group owner details with the ones found at discovery */
-                        groupOwner.updateSupplicantDetails(mPeers.get(groupOwner.deviceAddress));
-                        mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
-                        sendPeersChangedBroadcast();
+                        WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress);
+                        if (peer != null) {
+                            // update group owner details with peer details found at discovery
+                            groupOwner.updateSupplicantDetails(peer);
+                            mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
+                            sendPeersChangedBroadcast();
+                        } else {
+                            // A supplicant bug can lead to reporting an invalid
+                            // group owner address (all zeroes) at times. Avoid a
+                            // crash, but continue group creation since it is not
+                            // essential.
+                            logw("Unknown group owner " + groupOwner);
+                        }
                     }
                     transitionTo(mGroupCreatedState);
                     break;