Merge "Trace: add ALOGVs for easier debugging" into klp-dev
diff --git a/Android.mk b/Android.mk
index 166db4ee..4e5427a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -165,6 +165,7 @@
 	core/java/android/print/ILayoutResultCallback.aidl \
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
+	core/java/android/print/IPrintDocumentAdapterObserver.aidl \
 	core/java/android/print/IPrintJobStateChangeListener.aidl \
 	core/java/android/print/IPrintManager.aidl \
 	core/java/android/print/IPrintSpooler.aidl \
diff --git a/api/current.txt b/api/current.txt
index ff48db0..078ed53 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22,6 +22,7 @@
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
+    field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
@@ -13227,6 +13228,7 @@
     field public static final java.util.UUID EFFECT_TYPE_BASS_BOOST;
     field public static final java.util.UUID EFFECT_TYPE_ENV_REVERB;
     field public static final java.util.UUID EFFECT_TYPE_EQUALIZER;
+    field public static final java.util.UUID EFFECT_TYPE_LOUDNESS_ENHANCER;
     field public static final java.util.UUID EFFECT_TYPE_NS;
     field public static final java.util.UUID EFFECT_TYPE_PRESET_REVERB;
     field public static final java.util.UUID EFFECT_TYPE_VIRTUALIZER;
@@ -13384,6 +13386,7 @@
   }
 
   public class LoudnessEnhancer extends android.media.audiofx.AudioEffect {
+    ctor public LoudnessEnhancer(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException;
     method public float getTargetGain() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     method public void setTargetGain(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
     field public static final int PARAM_TARGET_GAIN_MB = 0; // 0x0
@@ -25632,10 +25635,8 @@
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
     method public static void beginDelayedTransition(android.view.ViewGroup, android.transition.Transition);
-    method public static android.transition.Transition getDefaultTransition();
     method public static void go(android.transition.Scene);
     method public static void go(android.transition.Scene, android.transition.Transition);
-    method public void setDefaultTransition(android.transition.Transition);
     method public void setTransition(android.transition.Scene, android.transition.Transition);
     method public void setTransition(android.transition.Scene, android.transition.Scene, android.transition.Transition);
     method public void transitionTo(android.transition.Scene);
@@ -25794,6 +25795,7 @@
     method public boolean equals(android.util.DisplayMetrics);
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
+    field public static final int DENSITY_400 = 400; // 0x190
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
     field public static final int DENSITY_HIGH = 240; // 0xf0
     field public static final int DENSITY_LOW = 120; // 0x78
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e29f8ea..193724d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -58,6 +58,7 @@
 import android.util.AttributeSet;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.ActionMode;
@@ -4846,36 +4847,19 @@
                 writer.println(mChangingConfigurations);
         writer.print(innerPrefix); writer.print("mCurrentConfig=");
                 writer.println(mCurrentConfig);
+
         if (mLoaderManager != null) {
             writer.print(prefix); writer.print("Loader Manager ");
                     writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
                     writer.println(":");
             mLoaderManager.dump(prefix + "  ", fd, writer, args);
         }
-        mFragments.dump(prefix, fd, writer, args);
-        writer.print(prefix); writer.println("View Hierarchy:");
-        dumpViewHierarchy(prefix + "  ", writer, getWindow().getDecorView());
-    }
 
-    private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
-        writer.print(prefix);
-        if (view == null) {
-            writer.println("null");
-            return;
-        }
-        writer.println(view.toString());
-        if (!(view instanceof ViewGroup)) {
-            return;
-        }
-        ViewGroup grp = (ViewGroup)view;
-        final int N = grp.getChildCount();
-        if (N <= 0) {
-            return;
-        }
-        prefix = prefix + "  ";
-        for (int i=0; i<N; i++) {
-            dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
-        }
+        mFragments.dump(prefix, fd, writer, args);
+
+        getWindow().getDecorView().getViewRootImpl().dump(prefix, fd, writer, args);
+
+        mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
     }
 
     /**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index df63ab3..347850a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -558,7 +558,7 @@
 
         public final void schedulePauseActivity(IBinder token, boolean finished,
                 boolean userLeaving, int configChanges) {
-            queueOrSendMessage(
+            sendMessage(
                     finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                     token,
                     (userLeaving ? 1 : 0),
@@ -567,32 +567,32 @@
 
         public final void scheduleStopActivity(IBinder token, boolean showWindow,
                 int configChanges) {
-           queueOrSendMessage(
+           sendMessage(
                 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
                 token, 0, configChanges);
         }
 
         public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
-            queueOrSendMessage(
+            sendMessage(
                 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
                 token);
         }
 
         public final void scheduleSleeping(IBinder token, boolean sleeping) {
-            queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
+            sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
         }
 
         public final void scheduleResumeActivity(IBinder token, int processState,
                 boolean isForward) {
             updateProcessState(processState, false);
-            queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
+            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
         }
 
         public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
             ResultData res = new ResultData();
             res.token = token;
             res.results = results;
-            queueOrSendMessage(H.SEND_RESULT, res);
+            sendMessage(H.SEND_RESULT, res);
         }
 
         // we use token to identify this activity without having to send the
@@ -626,7 +626,7 @@
 
             updatePendingConfiguration(curConfig);
 
-            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
+            sendMessage(H.LAUNCH_ACTIVITY, r);
         }
 
         public final void scheduleRelaunchActivity(IBinder token,
@@ -641,12 +641,12 @@
             data.intents = intents;
             data.token = token;
 
-            queueOrSendMessage(H.NEW_INTENT, data);
+            sendMessage(H.NEW_INTENT, data);
         }
 
         public final void scheduleDestroyActivity(IBinder token, boolean finishing,
                 int configChanges) {
-            queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
+            sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
                     configChanges);
         }
 
@@ -658,7 +658,7 @@
                     sync, false, mAppThread.asBinder(), sendingUser);
             r.info = info;
             r.compatInfo = compatInfo;
-            queueOrSendMessage(H.RECEIVER, r);
+            sendMessage(H.RECEIVER, r);
         }
 
         public final void scheduleCreateBackupAgent(ApplicationInfo app,
@@ -668,7 +668,7 @@
             d.compatInfo = compatInfo;
             d.backupMode = backupMode;
 
-            queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
+            sendMessage(H.CREATE_BACKUP_AGENT, d);
         }
 
         public final void scheduleDestroyBackupAgent(ApplicationInfo app,
@@ -677,7 +677,7 @@
             d.appInfo = app;
             d.compatInfo = compatInfo;
 
-            queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
+            sendMessage(H.DESTROY_BACKUP_AGENT, d);
         }
 
         public final void scheduleCreateService(IBinder token,
@@ -688,7 +688,7 @@
             s.info = info;
             s.compatInfo = compatInfo;
 
-            queueOrSendMessage(H.CREATE_SERVICE, s);
+            sendMessage(H.CREATE_SERVICE, s);
         }
 
         public final void scheduleBindService(IBinder token, Intent intent,
@@ -702,7 +702,7 @@
             if (DEBUG_SERVICE)
                 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                         + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
-            queueOrSendMessage(H.BIND_SERVICE, s);
+            sendMessage(H.BIND_SERVICE, s);
         }
 
         public final void scheduleUnbindService(IBinder token, Intent intent) {
@@ -710,7 +710,7 @@
             s.token = token;
             s.intent = intent;
 
-            queueOrSendMessage(H.UNBIND_SERVICE, s);
+            sendMessage(H.UNBIND_SERVICE, s);
         }
 
         public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
@@ -722,11 +722,11 @@
             s.flags = flags;
             s.args = args;
 
-            queueOrSendMessage(H.SERVICE_ARGS, s);
+            sendMessage(H.SERVICE_ARGS, s);
         }
 
         public final void scheduleStopService(IBinder token) {
-            queueOrSendMessage(H.STOP_SERVICE, token);
+            sendMessage(H.STOP_SERVICE, token);
         }
 
         public final void bindApplication(String processName,
@@ -763,24 +763,24 @@
             data.initProfileFile = profileFile;
             data.initProfileFd = profileFd;
             data.initAutoStopProfiler = false;
-            queueOrSendMessage(H.BIND_APPLICATION, data);
+            sendMessage(H.BIND_APPLICATION, data);
         }
 
         public final void scheduleExit() {
-            queueOrSendMessage(H.EXIT_APPLICATION, null);
+            sendMessage(H.EXIT_APPLICATION, null);
         }
 
         public final void scheduleSuicide() {
-            queueOrSendMessage(H.SUICIDE, null);
+            sendMessage(H.SUICIDE, null);
         }
 
         public void requestThumbnail(IBinder token) {
-            queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
+            sendMessage(H.REQUEST_THUMBNAIL, token);
         }
 
         public void scheduleConfigurationChanged(Configuration config) {
             updatePendingConfiguration(config);
-            queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
+            sendMessage(H.CONFIGURATION_CHANGED, config);
         }
 
         public void updateTimeZone() {
@@ -807,7 +807,7 @@
                 data.fd = ParcelFileDescriptor.dup(fd);
                 data.token = servicetoken;
                 data.args = args;
-                queueOrSendMessage(H.DUMP_SERVICE, data);
+                sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/);
             } catch (IOException e) {
                 Slog.w(TAG, "dumpService failed", e);
             }
@@ -825,11 +825,11 @@
         }
 
         public void scheduleLowMemory() {
-            queueOrSendMessage(H.LOW_MEMORY, null);
+            sendMessage(H.LOW_MEMORY, null);
         }
 
         public void scheduleActivityConfigurationChanged(IBinder token) {
-            queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
+            sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
         }
 
         public void profilerControl(boolean start, String path, ParcelFileDescriptor fd,
@@ -837,14 +837,14 @@
             ProfilerControlData pcd = new ProfilerControlData();
             pcd.path = path;
             pcd.fd = fd;
-            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType);
+            sendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType);
         }
 
         public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
             DumpHeapData dhd = new DumpHeapData();
             dhd.path = path;
             dhd.fd = fd;
-            queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0);
+            sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/);
         }
 
         public void setSchedulingGroup(int group) {
@@ -860,11 +860,11 @@
         }
 
         public void dispatchPackageBroadcast(int cmd, String[] packages) {
-            queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
+            sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
         }
 
         public void scheduleCrash(String msg) {
-            queueOrSendMessage(H.SCHEDULE_CRASH, msg);
+            sendMessage(H.SCHEDULE_CRASH, msg);
         }
 
         public void dumpActivity(FileDescriptor fd, IBinder activitytoken,
@@ -875,7 +875,7 @@
                 data.token = activitytoken;
                 data.prefix = prefix;
                 data.args = args;
-                queueOrSendMessage(H.DUMP_ACTIVITY, data);
+                sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/);
             } catch (IOException e) {
                 Slog.w(TAG, "dumpActivity failed", e);
             }
@@ -888,7 +888,7 @@
                 data.fd = ParcelFileDescriptor.dup(fd);
                 data.token = providertoken;
                 data.args = args;
-                queueOrSendMessage(H.DUMP_PROVIDER, data);
+                sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/);
             } catch (IOException e) {
                 Slog.w(TAG, "dumpProvider failed", e);
             }
@@ -1225,7 +1225,7 @@
 
         @Override
         public void unstableProviderDied(IBinder provider) {
-            queueOrSendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
+            sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
         }
 
         @Override
@@ -1235,7 +1235,7 @@
             cmd.activityToken = activityToken;
             cmd.requestToken = requestToken;
             cmd.requestType = requestType;
-            queueOrSendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
+            sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
         }
 
         private void printRow(PrintWriter pw, String format, Object...objs) {
@@ -1243,22 +1243,22 @@
         }
 
         public void setCoreSettings(Bundle coreSettings) {
-            queueOrSendMessage(H.SET_CORE_SETTINGS, coreSettings);
+            sendMessage(H.SET_CORE_SETTINGS, coreSettings);
         }
 
         public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
             UpdateCompatibilityData ucd = new UpdateCompatibilityData();
             ucd.pkg = pkg;
             ucd.info = info;
-            queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
+            sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
         }
 
         public void scheduleTrimMemory(int level) {
-            queueOrSendMessage(H.TRIM_MEMORY, null, level);
+            sendMessage(H.TRIM_MEMORY, null, level);
         }
 
         public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
-            queueOrSendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
+            sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
         }
 
         public void setProcessState(int state) {
@@ -1281,7 +1281,7 @@
 
         @Override
         public void scheduleInstallProvider(ProviderInfo provider) {
-            queueOrSendMessage(H.INSTALL_PROVIDER, provider);
+            sendMessage(H.INSTALL_PROVIDER, provider);
         }
     }
 
@@ -2033,28 +2033,31 @@
         mAppThread.scheduleSendResult(token, list);
     }
 
-    // if the thread hasn't started yet, we don't have the handler, so just
-    // save the messages until we're ready.
-    private void queueOrSendMessage(int what, Object obj) {
-        queueOrSendMessage(what, obj, 0, 0);
+    private void sendMessage(int what, Object obj) {
+        sendMessage(what, obj, 0, 0, false);
     }
 
-    private void queueOrSendMessage(int what, Object obj, int arg1) {
-        queueOrSendMessage(what, obj, arg1, 0);
+    private void sendMessage(int what, Object obj, int arg1) {
+        sendMessage(what, obj, arg1, 0, false);
     }
 
-    private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
-        synchronized (this) {
-            if (DEBUG_MESSAGES) Slog.v(
-                TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
-                + ": " + arg1 + " / " + obj);
-            Message msg = Message.obtain();
-            msg.what = what;
-            msg.obj = obj;
-            msg.arg1 = arg1;
-            msg.arg2 = arg2;
-            mH.sendMessage(msg);
+    private void sendMessage(int what, Object obj, int arg1, int arg2) {
+        sendMessage(what, obj, arg1, arg2, false);
+    }
+
+    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
+        if (DEBUG_MESSAGES) Slog.v(
+            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+            + ": " + arg1 + " / " + obj);
+        Message msg = Message.obtain();
+        msg.what = what;
+        msg.obj = obj;
+        msg.arg1 = arg1;
+        msg.arg2 = arg2;
+        if (async) {
+            msg.setAsynchronous(true);
         }
+        mH.sendMessage(msg);
     }
 
     final void scheduleContextCleanup(ContextImpl context, String who,
@@ -2063,7 +2066,7 @@
         cci.context = context;
         cci.who = who;
         cci.what = what;
-        queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
+        sendMessage(H.CLEAN_UP_CONTEXT, cci);
     }
 
     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
@@ -3592,7 +3595,7 @@
                     target.onlyLocalRequest = true;
                 }
                 mRelaunchingActivities.add(target);
-                queueOrSendMessage(H.RELAUNCH_ACTIVITY, target);
+                sendMessage(H.RELAUNCH_ACTIVITY, target);
             }
 
             if (fromServer) {
@@ -4900,7 +4903,7 @@
                                 mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                             mPendingConfiguration = newConfig;
                             
-                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
+                            sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                         }
                     }
                 }
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 5c3a3e5..27b5a5a9 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -109,21 +109,19 @@
     }
 
     /**
-     * TBW: discussion of fuzzy nature of alarms in KLP+.
-     *
      * <p>Schedule an alarm.  <b>Note: for timing operations (ticks, timeouts,
-     * etc) it is easier and much more efficient to use
-     * {@link android.os.Handler}.</b>  If there is already an alarm scheduled
-     * for the same IntentSender, it will first be canceled.
+     * etc) it is easier and much more efficient to use {@link android.os.Handler}.</b>
+     * If there is already an alarm scheduled for the same IntentSender, that previous
+     * alarm will first be canceled.
      *
-     * <p>If the time occurs in the past, the alarm will be triggered
+     * <p>If the stated trigger time is in the past, the alarm will be triggered
      * immediately.  If there is already an alarm for this Intent
      * scheduled (with the equality of two intents being defined by
      * {@link Intent#filterEquals}), then it will be removed and replaced by
      * this one.
      *
      * <p>
-     * The alarm is an intent broadcast that goes to a broadcast receiver that
+     * The alarm is an Intent broadcast that goes to a broadcast receiver that
      * you registered with {@link android.content.Context#registerReceiver}
      * or through the &lt;receiver&gt; tag in an AndroidManifest.xml file.
      *
@@ -133,9 +131,32 @@
      * how many past alarm events have been accumulated into this intent
      * broadcast.  Recurring alarms that have gone undelivered because the
      * phone was asleep may have a count greater than one when delivered.  
-     *  
-     * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or
-     *             RTC_WAKEUP.
+     *
+     * <p>
+     * <b>Note:</b> Beginning in API 19, the trigger time passed to this method
+     * is treated as inexact: the alarm will not be delivered before this time, but
+     * may be deferred and delivered some time later.  The OS will use
+     * this policy in order to "batch" alarms together across the entire system,
+     * minimizing the number of times the device needs to "wake up" and minimizing
+     * battery use.  In general, alarms scheduled in the near future will not
+     * be deferred as long as alarms scheduled far in the future.
+     *
+     * <p>
+     * With the new batching policy, delivery ordering guarantees are not as
+     * strong as they were previously.  If the application sets multiple alarms,
+     * it is possible that these alarms' <i>actual</i> delivery ordering may not match
+     * the order of their <i>requested</i> delivery times.  If your application has
+     * strong ordering requirements there are other APIs that you can use to get
+     * the necessary behavior; see {@link #setWindow(int, long, long, PendingIntent)}
+     * and {@link #setExact(int, long, PendingIntent)}.
+     *
+     * <p>
+     * <b>Note:</b> Applications whose targetSdkVersion is before API 19 will
+     * continue to get the previous alarm behavior: all of their scheduled alarms
+     * will be treated as exact.
+     *
+     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
+     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
      * @param triggerAtMillis time in milliseconds that the alarm should go
      * off, using the appropriate clock (depending on the alarm type).
      * @param operation Action to perform when the alarm goes off;
@@ -165,10 +186,10 @@
      * {@link android.os.Handler}.</b>  If there is already an alarm scheduled
      * for the same IntentSender, it will first be canceled.
      *
-     * <p>Like {@link #set}, except you can also
-     * supply a rate at which the alarm will repeat.  This alarm continues
-     * repeating until explicitly removed with {@link #cancel}.  If the time
-     * occurs in the past, the alarm will be triggered immediately, with an
+     * <p>Like {@link #set}, except you can also supply a period at which
+     * the alarm will automatically repeat.  This alarm continues
+     * repeating until explicitly removed with {@link #cancel}.  If the stated
+     * trigger time is in the past, the alarm will be triggered immediately, with an
      * alarm count depending on how far in the past the trigger time is relative
      * to the repeat interval.
      *
@@ -185,8 +206,15 @@
      * between alarms, then the approach to take is to use one-time alarms, 
      * scheduling the next one yourself when handling each alarm delivery.
      *
-     * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP}, RTC or
-     *             RTC_WAKEUP.
+     * <p>
+     * <b>Note:</b> as of API 19, all repeating alarms are inexact.  If your
+     * application needs precise delivery times then it must use one-time
+     * exact alarms, rescheduling each time as described above. Legacy applications
+     * whose targetSdkVersion is earlier than API 19 will continue to have all
+     * of their alarms, including repeating alarms, treated as exact.
+     *
+     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
+     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
      * @param triggerAtMillis time in milliseconds that the alarm should first
      * go off, using the appropriate clock (depending on the alarm type).
      * @param intervalMillis interval in milliseconds between subsequent repeats
@@ -214,18 +242,32 @@
     }
 
     /**
-     * Schedule an alarm to be delivered within a given window of time.
+     * Schedule an alarm to be delivered within a given window of time.  This method
+     * is similar to {@link #set(int, long, PendingIntent)}, but allows the
+     * application to precisely control the degree to which its delivery might be
+     * adjusted by the OS. This method allows an application to take advantage of the
+     * battery optimizations that arise from delivery batching even when it has
+     * modest timeliness requirements for its alarms.
      *
-     * TBW: clean up these docs
+     * <p>
+     * This method can also be used to achieve strict ordering guarantees by ensuring
+     * that the windows requested for each alarm do not intersect.
      *
-     * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or
-     *        RTC_WAKEUP.
+     * <p>
+     * When precise delivery is not required, applications should use the standard
+     * {@link #set(int, long, PendingIntent)} method.  This will give the OS the most
+     * ability to minimize wakeups and battery use.  For alarms that must be delivered
+     * at precisely-specified times with no acceptable variation, applications can use
+     * {@link #setExact(int, long, PendingIntent)}.
+     *
+     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
+     *        {@link #RTC}, or {@link #RTC_WAKEUP
      * @param windowStartMillis The earliest time, in milliseconds, that the alarm should
      *        be delivered, expressed in the appropriate clock's units (depending on the alarm
      *        type).
      * @param windowLengthMillis The length of the requested delivery window,
      *        in milliseconds.  The alarm will be delivered no later than this many
-     *        milliseconds after the windowStartMillis time.  Note that this parameter
+     *        milliseconds after {@code windowStartMillis}.  Note that this parameter
      *        is a <i>duration,</i> not the timestamp of the end of the window.
      * @param operation Action to perform when the alarm goes off;
      *        typically comes from {@link PendingIntent#getBroadcast
@@ -249,8 +291,38 @@
     }
 
     /**
-     * TBW: new 'exact' alarm that must be delivered as nearly as possible
-     * to the precise time specified.
+     * Schedule an alarm to be delivered precisely at the stated time.
+     *
+     * <p>
+     * This method is like {@link #set(int, long, PendingIntent)}, but does not permit
+     * the OS to adjust the delivery time.  The alarm will be delivered as nearly as
+     * possible to the requested trigger time.
+     *
+     * <p>
+     * <b>Note:</b> only alarms for which there is a strong demand for exact-time
+     * delivery (such as an alarm clock ringing at the requested time) should be
+     * scheduled as exact.  Applications are strongly discouraged from using exact
+     * alarms unnecessarily as they reduce the OS's ability to minimize battery use.
+     *
+     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
+     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
+     * @param triggerAtMillis time in milliseconds that the alarm should go
+     *        off, using the appropriate clock (depending on the alarm type).
+     * @param operation Action to perform when the alarm goes off;
+     *        typically comes from {@link PendingIntent#getBroadcast
+     *        IntentSender.getBroadcast()}.
+     *
+     * @see #set
+     * @see #setRepeating
+     * @see #setWindow
+     * @see #cancel
+     * @see android.content.Context#sendBroadcast
+     * @see android.content.Context#registerReceiver
+     * @see android.content.Intent#filterEquals
+     * @see #ELAPSED_REALTIME
+     * @see #ELAPSED_REALTIME_WAKEUP
+     * @see #RTC
+     * @see #RTC_WAKEUP
      */
     public void setExact(int type, long triggerAtMillis, PendingIntent operation) {
         setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation, null);
@@ -332,8 +404,8 @@
      * may vary.  If your application demands very low jitter, use
      * {@link #setRepeating} instead.
      *
-     * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP}, RTC or
-     *             RTC_WAKEUP.
+     * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP},
+     *        {@link #RTC}, or {@link #RTC_WAKEUP}.
      * @param triggerAtMillis time in milliseconds that the alarm should first
      * go off, using the appropriate clock (depending on the alarm type).  This
      * is inexact: the alarm will not fire before this time, but there may be a
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 5822e46..d789a944 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -322,7 +322,7 @@
 
     /**
      * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} to
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to
      * receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -465,7 +465,7 @@
 
     /**
      * The user will be prompted to enter a pin or
-     * a privileged app will enter a pin for user.
+     * an app will enter a pin for user.
      */
     public static final int PAIRING_VARIANT_PIN = 0;
 
@@ -477,7 +477,7 @@
 
     /**
      * The user will be prompted to confirm the passkey displayed on the screen or
-     * a privileged app will confirm the passkey for the user.
+     * an app will confirm the passkey for the user.
      */
     public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
 
@@ -725,7 +725,7 @@
      * the bonding process completes, and its result.
      * <p>Android system services will handle the necessary user interactions
      * to confirm and complete the bonding process.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
      *
      * @return false on immediate error, true if bonding will begin
      */
@@ -965,7 +965,7 @@
 
     /**
      * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
      *
      * @return true pin has been set
      *         false for error
@@ -993,7 +993,7 @@
 
     /**
      * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
      *
      * @return true confirmation has been sent out
      *         false for error
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 14f67c5..50fdb41 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -358,14 +358,20 @@
             mListener = listener;
         }
 
+        @Override
         public void addSensorEvent(Sensor sensor) {
             SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
                     mManager.mTargetSdkLevel));
-            mSensorsEvents.put(sensor.getHandle(), t);
+            synchronized (mSensorsEvents) {
+                mSensorsEvents.put(sensor.getHandle(), t);
+            }
         }
 
+        @Override
         public void removeSensorEvent(Sensor sensor) {
-            mSensorsEvents.delete(sensor.getHandle());
+            synchronized (mSensorsEvents) {
+                mSensorsEvents.delete(sensor.getHandle());
+            }
         }
 
         // Called from native code.
@@ -374,9 +380,14 @@
         protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                 long timestamp) {
             final Sensor sensor = sHandleToSensor.get(handle);
-            SensorEvent t = mSensorsEvents.get(handle);
+            SensorEvent t = null;
+            synchronized (mSensorsEvents) {
+                t = mSensorsEvents.get(handle);
+            }
+
             if (t == null) {
-                Log.e(TAG, "Error: Sensor Event is null for Sensor: " + sensor);
+                // This may happen if the client has unregistered and there are pending events in
+                // the queue waiting to be delivered. Ignore.
                 return;
             }
             // Copy from the values array.
@@ -427,14 +438,20 @@
             mListener = listener;
         }
 
+        @Override
         public void addSensorEvent(Sensor sensor) {
             TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
                     mManager.mTargetSdkLevel));
-            mTriggerEvents.put(sensor.getHandle(), t);
+            synchronized (mTriggerEvents) {
+                mTriggerEvents.put(sensor.getHandle(), t);
+            }
         }
 
+        @Override
         public void removeSensorEvent(Sensor sensor) {
-            mTriggerEvents.delete(sensor.getHandle());
+            synchronized (mTriggerEvents) {
+                mTriggerEvents.delete(sensor.getHandle());
+            }
         }
 
         // Called from native code.
@@ -443,7 +460,10 @@
         protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
                 long timestamp) {
             final Sensor sensor = sHandleToSensor.get(handle);
-            TriggerEvent t = mTriggerEvents.get(handle);
+            TriggerEvent t = null;
+            synchronized (mTriggerEvents) {
+                t = mTriggerEvents.get(handle);
+            }
             if (t == null) {
                 Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
                 return;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 486e75a..6743c6c 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -49,6 +49,8 @@
  * <h3>Developer Guides</h3>
  * <p>For more information about using NFC, read the
  * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
+ * <p>To perform basic file sharing between devices, read
+ * <a href="{@docRoot}training/beam-files/index.html">Sharing Files with NFC</a>.
  * </div>
  */
 public final class NfcAdapter {
@@ -309,8 +311,12 @@
     final Context mContext;
 
     /**
-     * A callback to be invoked when the system has found a tag in
-     * reader mode.
+     * A callback to be invoked when the system finds a tag while the foreground activity is
+     * operating in reader mode.
+     * <p>Register your {@code ReaderCallback} implementation with {@link
+     * NfcAdapter#enableReaderMode} and disable it with {@link
+     * NfcAdapter#disableReaderMode}.
+     * @see NfcAdapter#enableReaderMode
      */
     public interface ReaderCallback {
         public void onTagDiscovered(Tag tag);
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 5a919fb..f9c1d31 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -35,10 +35,12 @@
     public static final Bundle EMPTY;
 
     static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+    static final Parcel EMPTY_PARCEL;
 
     static {
         EMPTY = new Bundle();
         EMPTY.mMap = ArrayMap.EMPTY;
+        EMPTY_PARCEL = Parcel.obtain();
     }
 
     // Invariant - exactly one of mMap / mParcelledData will be null
@@ -115,9 +117,13 @@
      */
     public Bundle(Bundle b) {
         if (b.mParcelledData != null) {
-            mParcelledData = Parcel.obtain();
-            mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
-            mParcelledData.setDataPosition(0);
+            if (b.mParcelledData == EMPTY_PARCEL) {
+                mParcelledData = EMPTY_PARCEL;
+            } else {
+                mParcelledData = Parcel.obtain();
+                mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
+                mParcelledData.setDataPosition(0);
+            }
         } else {
             mParcelledData = null;
         }
@@ -216,6 +222,18 @@
             return;
         }
 
+        if (mParcelledData == EMPTY_PARCEL) {
+            if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+                    + ": empty");
+            if (mMap == null) {
+                mMap = new ArrayMap<String, Object>(1);
+            } else {
+                mMap.erase();
+            }
+            mParcelledData = null;
+            return;
+        }
+
         int N = mParcelledData.readInt();
         if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                 + ": reading " + N + " maps");
@@ -1652,11 +1670,20 @@
         final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
         try {
             if (mParcelledData != null) {
-                int length = mParcelledData.dataSize();
-                parcel.writeInt(length);
-                parcel.writeInt(BUNDLE_MAGIC);
-                parcel.appendFrom(mParcelledData, 0, length);
+                if (mParcelledData == EMPTY_PARCEL) {
+                    parcel.writeInt(0);
+                } else {
+                    int length = mParcelledData.dataSize();
+                    parcel.writeInt(length);
+                    parcel.writeInt(BUNDLE_MAGIC);
+                    parcel.appendFrom(mParcelledData, 0, length);
+                }
             } else {
+                // Special case for empty bundles.
+                if (mMap == null || mMap.size() <= 0) {
+                    parcel.writeInt(0);
+                    return;
+                }
                 int lengthPos = parcel.dataPosition();
                 parcel.writeInt(-1); // dummy, will hold length
                 parcel.writeInt(BUNDLE_MAGIC);
@@ -1690,6 +1717,13 @@
     }
 
     void readFromParcelInner(Parcel parcel, int length) {
+        if (length == 0) {
+            // Empty Bundle or end of data.
+            mParcelledData = EMPTY_PARCEL;
+            mHasFds = false;
+            mFdsKnown = true;
+            return;
+        }
         int magic = parcel.readInt();
         if (magic != BUNDLE_MAGIC) {
             //noinspection ThrowableInstanceNeverThrown
@@ -1716,8 +1750,12 @@
     @Override
     public synchronized String toString() {
         if (mParcelledData != null) {
-            return "Bundle[mParcelledData.dataSize=" +
-                    mParcelledData.dataSize() + "]";
+            if (mParcelledData == EMPTY_PARCEL) {
+                return "Bundle[EMPTY_PARCEL]";
+            } else {
+                return "Bundle[mParcelledData.dataSize=" +
+                        mParcelledData.dataSize() + "]";
+            }
         }
         return "Bundle[" + mMap.toString() + "]";
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 4d48fd4..ff3e277 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -144,13 +144,6 @@
         }
     }
 
-    /** returns the FAT file system volume ID for the volume mounted 
-     * at the given mount point, or -1 for failure
-     * @param mountPoint point for FAT volume
-     * @return volume ID or -1
-     */
-    public static native int getFatVolumeId(String mountPoint);
-
     /**
      * Perform an fsync on the given FileOutputStream.  The stream at this
      * point must be flushed but not yet closed.
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 4c7bbb4..56176a4 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,11 +23,12 @@
 
 interface IPowerManager
 {
-    // WARNING: The first three methods must remain the first three methods because their
+    // WARNING: The first four methods must remain the first three methods because their
     // transaction numbers must not change unless IPowerManager.cpp is also updated.
     void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws);
     void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, int uidtoblame);
     void releaseWakeLock(IBinder lock, int flags);
+    void updateWakeLockUids(IBinder lock, in int[] uids);
 
     void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
     boolean isWakeLockLevelSupported(int level);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 78c859e..21e9f6b 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -59,7 +59,6 @@
 
     final MessageQueue mQueue;
     final Thread mThread;
-    volatile boolean mRun;
 
     private Printer mLogging;
 
@@ -187,7 +186,6 @@
 
     private Looper(boolean quitAllowed) {
         mQueue = new MessageQueue(quitAllowed);
-        mRun = true;
         mThread = Thread.currentThread();
     }
 
@@ -300,27 +298,12 @@
     }
 
     public void dump(Printer pw, String prefix) {
-        pw = PrefixPrinter.create(pw, prefix);
-        pw.println(this.toString());
-        pw.println("mRun=" + mRun);
-        pw.println("mThread=" + mThread);
-        pw.println("mQueue=" + ((mQueue != null) ? mQueue : "(null"));
-        if (mQueue != null) {
-            synchronized (mQueue) {
-                long now = SystemClock.uptimeMillis();
-                Message msg = mQueue.mMessages;
-                int n = 0;
-                while (msg != null) {
-                    pw.println("  Message " + n + ": " + msg.toString(now));
-                    n++;
-                    msg = msg.next;
-                }
-                pw.println("(Total messages: " + n + ")");
-            }
-        }
+        pw.println(prefix + toString());
+        mQueue.dump(pw, prefix + "  ");
     }
 
     public String toString() {
-        return "Looper{" + Integer.toHexString(System.identityHashCode(this)) + "}";
+        return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
+                + ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
     }
 }
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 0abc149..51203a48 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -428,36 +428,48 @@
     public Message() {
     }
 
+    @Override
     public String toString() {
         return toString(SystemClock.uptimeMillis());
     }
 
     String toString(long now) {
-        StringBuilder   b = new StringBuilder();
-        
-        b.append("{ what=");
-        b.append(what);
+        StringBuilder b = new StringBuilder();
+        b.append("{ when=");
+        TimeUtils.formatDuration(when - now, b);
 
-        b.append(" when=");
-        TimeUtils.formatDuration(when-now, b);
+        if (target != null) {
+            if (callback != null) {
+                b.append(" callback=");
+                b.append(callback.getClass().getName());
+            } else {
+                b.append(" what=");
+                b.append(what);
+            }
 
-        if (arg1 != 0) {
-            b.append(" arg1=");
+            if (arg1 != 0) {
+                b.append(" arg1=");
+                b.append(arg1);
+            }
+
+            if (arg2 != 0) {
+                b.append(" arg2=");
+                b.append(arg2);
+            }
+
+            if (obj != null) {
+                b.append(" obj=");
+                b.append(obj);
+            }
+
+            b.append(" target=");
+            b.append(target.getClass().getName());
+        } else {
+            b.append(" barrier=");
             b.append(arg1);
         }
 
-        if (arg2 != 0) {
-            b.append(" arg2=");
-            b.append(arg2);
-        }
-
-        if (obj != null) {
-            b.append(" obj=");
-            b.append(obj);
-        }
-
         b.append(" }");
-        
         return b.toString();
     }
 
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index d1b8213..799de5c 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -18,6 +18,7 @@
 
 import android.util.AndroidRuntimeException;
 import android.util.Log;
+import android.util.Printer;
 
 import java.util.ArrayList;
 
@@ -252,6 +253,7 @@
         synchronized (this) {
             final int token = mNextBarrierToken++;
             final Message msg = Message.obtain();
+            msg.when = when;
             msg.arg1 = token;
 
             Message prev = null;
@@ -393,12 +395,16 @@
 
     boolean isIdling() {
         synchronized (this) {
-            // If the loop is quitting then it must not be idling.
-            // We can assume mPtr != 0 when mQuitting is false.
-            return !mQuitting && nativeIsIdling(mPtr);
+            return isIdlingLocked();
         }
     }
 
+    private boolean isIdlingLocked() {
+        // If the loop is quitting then it must not be idling.
+        // We can assume mPtr != 0 when mQuitting is false.
+        return !mQuitting && nativeIsIdling(mPtr);
+     }
+
     void removeMessages(Handler h, int what, Object object) {
         if (h == null) {
             return;
@@ -537,4 +543,17 @@
             }
         }
     }
+
+    void dump(Printer pw, String prefix) {
+        synchronized (this) {
+            long now = SystemClock.uptimeMillis();
+            int n = 0;
+            for (Message msg = mMessages; msg != null; msg = msg.next) {
+                pw.println(prefix + "Message " + n + ": " + msg.toString(now));
+                n++;
+            }
+            pw.println(prefix + "(Total messages: " + n + ", idling=" + isIdlingLocked()
+                    + ", quitting=" + mQuitting + ")");
+        }
+    }
 }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 02b1998..94b9617 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -611,11 +611,15 @@
             here.fillInStackTrace();
             Log.d(TAG, "Writing " + N + " ArrayMap entries", here);
         }
+        int startPos;
         for (int i=0; i<N; i++) {
-            if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Write #" + i + ": key=0x"
-                    + (val.keyAt(i) != null ? val.keyAt(i).hashCode() : 0) + " " + val.keyAt(i));
+            if (DEBUG_ARRAY_MAP) startPos = dataPosition();
             writeValue(val.keyAt(i));
             writeValue(val.valueAt(i));
+            if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Write #" + i + " "
+                    + (dataPosition()-startPos) + " bytes: key=0x"
+                    + Integer.toHexString(val.keyAt(i) != null ? val.keyAt(i).hashCode() : 0)
+                    + " " + val.keyAt(i));
         }
     }
 
@@ -2303,11 +2307,14 @@
             here.fillInStackTrace();
             Log.d(TAG, "Reading " + N + " ArrayMap entries", here);
         }
+        int startPos;
         while (N > 0) {
+            if (DEBUG_ARRAY_MAP) startPos = dataPosition();
             Object key = readValue(loader);
-            if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Read #" + (N-1) + ": key=0x"
-                    + (key != null ? key.hashCode() : 0) + " " + key);
             Object value = readValue(loader);
+            if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Read #" + (N-1) + " "
+                    + (dataPosition()-startPos) + " bytes: key=0x"
+                    + Integer.toHexString((key != null ? key.hashCode() : 0)) + " " + key);
             outVal.append(key, value);
             N--;
         }
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 1456387..5273c20 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -231,10 +231,11 @@
         final FileDescriptor fd = openInternal(file, mode);
         if (fd == null) return null;
 
-        final FileDescriptor[] comm = createCommSocketPair(true);
+        final FileDescriptor[] comm = createCommSocketPair();
         final ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]);
 
         // Kick off thread to watch for status updates
+        IoUtils.setBlocking(comm[1], true);
         final ListenerBridge bridge = new ListenerBridge(comm[1], handler.getLooper(), listener);
         bridge.start();
 
@@ -378,7 +379,7 @@
      */
     public static ParcelFileDescriptor[] createReliablePipe() throws IOException {
         try {
-            final FileDescriptor[] comm = createCommSocketPair(false);
+            final FileDescriptor[] comm = createCommSocketPair();
             final FileDescriptor[] fds = Libcore.os.pipe();
             return new ParcelFileDescriptor[] {
                     new ParcelFileDescriptor(fds[0], comm[0]),
@@ -416,7 +417,7 @@
      */
     public static ParcelFileDescriptor[] createReliableSocketPair() throws IOException {
         try {
-            final FileDescriptor[] comm = createCommSocketPair(false);
+            final FileDescriptor[] comm = createCommSocketPair();
             final FileDescriptor fd0 = new FileDescriptor();
             final FileDescriptor fd1 = new FileDescriptor();
             Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
@@ -428,13 +429,13 @@
         }
     }
 
-    private static FileDescriptor[] createCommSocketPair(boolean blocking) throws IOException {
+    private static FileDescriptor[] createCommSocketPair() throws IOException {
         try {
             final FileDescriptor comm1 = new FileDescriptor();
             final FileDescriptor comm2 = new FileDescriptor();
             Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2);
-            IoUtils.setBlocking(comm1, blocking);
-            IoUtils.setBlocking(comm2, blocking);
+            IoUtils.setBlocking(comm1, false);
+            IoUtils.setBlocking(comm2, false);
             return new FileDescriptor[] { comm1, comm2 };
         } catch (ErrnoException e) {
             throw e.rethrowAsIOException();
@@ -670,34 +671,35 @@
         }
 
         try {
+            if (status == Status.SILENCE) return;
+
+            // Since we're about to close, read off any remote status. It's
+            // okay to remember missing here.
+            mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
+
+            // Skip writing status when other end has already gone away.
+            if (mStatus != null) return;
+
             try {
-                if (status != Status.SILENCE) {
-                    final byte[] buf = getOrCreateStatusBuffer();
-                    int writePtr = 0;
+                final byte[] buf = getOrCreateStatusBuffer();
+                int writePtr = 0;
 
-                    Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN);
-                    writePtr += 4;
+                Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN);
+                writePtr += 4;
 
-                    if (msg != null) {
-                        final byte[] rawMsg = msg.getBytes();
-                        final int len = Math.min(rawMsg.length, buf.length - writePtr);
-                        System.arraycopy(rawMsg, 0, buf, writePtr, len);
-                        writePtr += len;
-                    }
-
-                    Libcore.os.write(mCommFd, buf, 0, writePtr);
+                if (msg != null) {
+                    final byte[] rawMsg = msg.getBytes();
+                    final int len = Math.min(rawMsg.length, buf.length - writePtr);
+                    System.arraycopy(rawMsg, 0, buf, writePtr, len);
+                    writePtr += len;
                 }
+
+                Libcore.os.write(mCommFd, buf, 0, writePtr);
             } catch (ErrnoException e) {
                 // Reporting status is best-effort
                 Log.w(TAG, "Failed to report status: " + e);
             }
 
-            if (status != Status.SILENCE) {
-                // Since we're about to close, read off any remote status. It's
-                // okay to remember missing here.
-                mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
-            }
-
         } finally {
             IoUtils.closeQuietly(mCommFd);
             mCommFd = null;
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 177a955..0285cb9 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -21,6 +21,9 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.CharArrayWriter;
 import java.io.File;
 
 /**
@@ -46,6 +49,10 @@
     /** When set, indicates exclusive ownership of this volume */
     private final UserHandle mOwner;
 
+    private String mUuid;
+    private String mUserLabel;
+    private String mState;
+
     // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
     // ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
     // ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
@@ -76,6 +83,9 @@
         mAllowMassStorage = in.readInt() != 0;
         mMaxFileSize = in.readLong();
         mOwner = in.readParcelable(null);
+        mUuid = in.readString();
+        mUserLabel = in.readString();
+        mState = in.readString();
     }
 
     public static StorageVolume fromTemplate(StorageVolume template, File path, UserHandle owner) {
@@ -189,6 +199,45 @@
         return mOwner;
     }
 
+    public void setUuid(String uuid) {
+        mUuid = uuid;
+    }
+
+    public String getUuid() {
+        return mUuid;
+    }
+
+    /**
+     * Parse and return volume UUID as FAT volume ID, or return -1 if unable to
+     * parse or UUID is unknown.
+     */
+    public int getFatVolumeId() {
+        if (mUuid == null || mUuid.length() != 9) {
+            return -1;
+        }
+        try {
+            return Integer.parseInt(mUuid.replace("-", ""), 16);
+        } catch (NumberFormatException e) {
+            return -1;
+        }
+    }
+
+    public void setUserLabel(String userLabel) {
+        mUserLabel = userLabel;
+    }
+
+    public String getUserLabel() {
+        return mUserLabel;
+    }
+
+    public void setState(String state) {
+        mState = state;
+    }
+
+    public String getState() {
+        return mState;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof StorageVolume && mPath != null) {
@@ -205,19 +254,28 @@
 
     @Override
     public String toString() {
-        final StringBuilder builder = new StringBuilder("StorageVolume [");
-        builder.append("mStorageId=").append(mStorageId);
-        builder.append(" mPath=").append(mPath);
-        builder.append(" mDescriptionId=").append(mDescriptionId);
-        builder.append(" mPrimary=").append(mPrimary);
-        builder.append(" mRemovable=").append(mRemovable);
-        builder.append(" mEmulated=").append(mEmulated);
-        builder.append(" mMtpReserveSpace=").append(mMtpReserveSpace);
-        builder.append(" mAllowMassStorage=").append(mAllowMassStorage);
-        builder.append(" mMaxFileSize=").append(mMaxFileSize);
-        builder.append(" mOwner=").append(mOwner);
-        builder.append("]");
-        return builder.toString();
+        final CharArrayWriter writer = new CharArrayWriter();
+        dump(new IndentingPrintWriter(writer, "    ", 80));
+        return writer.toString();
+    }
+
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("StorageVolume:");
+        pw.increaseIndent();
+        pw.printPair("mStorageId", mStorageId);
+        pw.printPair("mPath", mPath);
+        pw.printPair("mDescriptionId", mDescriptionId);
+        pw.printPair("mPrimary", mPrimary);
+        pw.printPair("mRemovable", mRemovable);
+        pw.printPair("mEmulated", mEmulated);
+        pw.printPair("mMtpReserveSpace", mMtpReserveSpace);
+        pw.printPair("mAllowMassStorage", mAllowMassStorage);
+        pw.printPair("mMaxFileSize", mMaxFileSize);
+        pw.printPair("mOwner", mOwner);
+        pw.printPair("mUuid", mUuid);
+        pw.printPair("mUserLabel", mUserLabel);
+        pw.printPair("mState", mState);
+        pw.decreaseIndent();
     }
 
     public static final Creator<StorageVolume> CREATOR = new Creator<StorageVolume>() {
@@ -249,5 +307,8 @@
         parcel.writeInt(mAllowMassStorage ? 1 : 0);
         parcel.writeLong(mMaxFileSize);
         parcel.writeParcelable(mOwner, flags);
+        parcel.writeString(mUuid);
+        parcel.writeString(mUserLabel);
+        parcel.writeString(mState);
     }
 }
diff --git a/core/java/android/print/IPrintDocumentAdapter.aidl b/core/java/android/print/IPrintDocumentAdapter.aidl
index b12c922..9d384fb 100644
--- a/core/java/android/print/IPrintDocumentAdapter.aidl
+++ b/core/java/android/print/IPrintDocumentAdapter.aidl
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.print.ILayoutResultCallback;
+import android.print.IPrintDocumentAdapterObserver;
 import android.print.IWriteResultCallback;
 import android.print.PageRange;
 import android.print.PrintAttributes;
@@ -29,6 +30,7 @@
  * @hide
  */
 oneway interface IPrintDocumentAdapter {
+    void setObserver(in IPrintDocumentAdapterObserver observer);
     void start();
     void layout(in PrintAttributes oldAttributes, in PrintAttributes newAttributes,
             ILayoutResultCallback callback, in Bundle metadata, int sequence);
diff --git a/core/java/android/print/IPrintDocumentAdapterObserver.aidl b/core/java/android/print/IPrintDocumentAdapterObserver.aidl
new file mode 100644
index 0000000..4443df0
--- /dev/null
+++ b/core/java/android/print/IPrintDocumentAdapterObserver.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.print;
+
+/**
+ * Interface for observing the state of a print document adapter.
+ *
+ * @hide
+ */
+oneway interface IPrintDocumentAdapterObserver {
+    void onDestroy();
+}
diff --git a/core/java/android/print/PageRange.java b/core/java/android/print/PageRange.java
index cdcd0c7..d6320f0 100644
--- a/core/java/android/print/PageRange.java
+++ b/core/java/android/print/PageRange.java
@@ -39,9 +39,8 @@
      * @param start The start page index (zero based and inclusive).
      * @param end The end page index (zero based and inclusive).
      *
-     * @throws IllegalArgumentException If start is less than zero.
-     * @throws IllegalArgumentException If end is less than zero.
-     * @throws IllegalArgumentException If start greater than end.
+     * @throws IllegalArgumentException If start is less than zero or end
+     * is less than zero or start greater than end.
      */
     public PageRange(int start, int end) {
         if (start < 0) {
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index e1a9cb7..c6254e0 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -30,7 +30,11 @@
 import java.util.Map;
 
 /**
- * This class represents the attributes of a print job.
+ * This class represents the attributes of a print job. These attributes
+ * describe how the printed content should be laid out. For example, the
+ * print attributes may state that the content should be laid out on a
+ * letter size with 300 DPI (dots per inch) resolution, have a margin of
+ * 10 mills (thousand of an inch) on all sides, and be black and white.
  */
 public final class PrintAttributes implements Parcelable {
     /** Color mode: Monochrome color scheme, for example one color is used. */
@@ -277,7 +281,7 @@
          * Unknown media size in portrait mode.
          * <p>
          * <strong>Note: </strong>This is for specifying orientation without media
-         * size. You should not use the dimensions reported by this class.
+         * size. You should not use the dimensions reported by this instance.
          * </p>
          */
         public static final MediaSize UNKNOWN_PORTRAIT =
@@ -288,7 +292,7 @@
          * Unknown media size in landscape mode.
          * <p>
          * <strong>Note: </strong>This is for specifying orientation without media
-         * size. You should not use the dimensions reported by this class.
+         * size. You should not use the dimensions reported by this instance.
          * </p>
          */
         public static final MediaSize UNKNOWN_LANDSCAPE =
@@ -615,9 +619,7 @@
         private final int mHeightMils;
 
         /**
-         * Creates a new instance. This is the preferred constructor since
-         * it enables the media size label to be shown in a localized fashion
-         * on a locale change.
+         * Creates a new instance.
          *
          * @param id The unique media size id.
          * @param packageName The name of the creating package.
@@ -625,10 +627,9 @@
          * @param widthMils The width in mils (thousands of an inch).
          * @param heightMils The height in mils (thousands of an inch).
          *
-         * @throws IllegalArgumentException If the id is empty.
-         * @throws IllegalArgumentException If the label is empty.
-         * @throws IllegalArgumentException If the widthMils is less than or equal to zero.
-         * @throws IllegalArgumentException If the heightMils is less than or equal to zero.
+         * @throws IllegalArgumentException If the id is empty or the label
+         * is empty or the widthMils is less than or equal to zero or the
+         * heightMils is less than or equal to zero.
          *
          * @hide
          */
@@ -667,14 +668,13 @@
          *
          * @param id The unique media size id. It is unique amongst other media sizes
          *        supported by the printer.
-         * @param label The <strong>internationalized</strong> human readable label.
+         * @param label The <strong>localized</strong> human readable label.
          * @param widthMils The width in mils (thousands of an inch).
          * @param heightMils The height in mils (thousands of an inch).
          *
-         * @throws IllegalArgumentException If the id is empty.
-         * @throws IllegalArgumentException If the label is empty.
-         * @throws IllegalArgumentException If the widthMils is less than or equal to zero.
-         * @throws IllegalArgumentException If the heightMils is less than or equal to zero.
+         * @throws IllegalArgumentException If the id is empty or the label is empty
+         * or the widthMils is less than or equal to zero or the heightMils is less
+         * than or equal to zero.
          */
         public MediaSize(String id, String label, int widthMils, int heightMils) {
             if (TextUtils.isEmpty(id)) {
@@ -776,12 +776,16 @@
         }
 
         /**
-         * Returns a new media size in a portrait orientation
+         * Returns a new media size instance in a portrait orientation,
          * which is the height is the greater dimension.
          *
-         * @return New instance in landscape orientation.
+         * @return New instance in landscape orientation if this one
+         * is in landscape, otherwise this instance.
          */
         public MediaSize asPortrait() {
+            if (isPortrait()) {
+                return this;
+            }
             return new MediaSize(mId, mLabel, mPackageName,
                     Math.min(mWidthMils, mHeightMils),
                     Math.max(mWidthMils, mHeightMils),
@@ -789,12 +793,16 @@
         }
 
         /**
-         * Returns a new media size in a landscape orientation
+         * Returns a new media size instance in a landscape orientation,
          * which is the height is the lesser dimension.
          *
-         * @return New instance in landscape orientation.
+         * @return New instance in landscape orientation if this one
+         * is in portrait, otherwise this instance.
          */
         public MediaSize asLandscape() {
+            if (!isPortrait()) {
+                return this;
+            }
             return new MediaSize(mId, mLabel, mPackageName,
                     Math.max(mWidthMils, mHeightMils),
                     Math.min(mWidthMils, mHeightMils),
@@ -881,8 +889,8 @@
      * This class specifies a supported resolution in DPI (dots per inch).
      * Resolution defines how many points with different color can be placed
      * on one inch in horizontal or vertical direction of the target media.
-     * For example, a printer with 600DIP can produce higher quality images
-     * the one with 300DPI resolution.
+     * For example, a printer with 600 DPI can produce higher quality images
+     * the one with 300 DPI resolution.
      */
     public static final class Resolution {
         private final String mId;
@@ -895,14 +903,13 @@
          *
          * @param id The unique resolution id. It is unique amongst other resolutions
          *        supported by the printer.
-         * @param label The <strong>internationalized</strong> human readable label.
+         * @param label The <strong>localized</strong> human readable label.
          * @param horizontalDpi The horizontal resolution in DPI (dots per inch).
          * @param verticalDpi The vertical resolution in DPI (dots per inch).
          *
-         * @throws IllegalArgumentException If the id is empty.
-         * @throws IllegalArgumentException If the label is empty.
-         * @throws IllegalArgumentException If the horizontalDpi is less than or equal to zero.
-         * @throws IllegalArgumentException If the verticalDpi is less than or equal to zero.
+         * @throws IllegalArgumentException If the id is empty or the label is empty
+         * or the horizontalDpi is less than or equal to zero or the verticalDpi is
+         * less than or equal to zero.
          */
         public Resolution(String id, String label, int horizontalDpi, int verticalDpi) {
             if (TextUtils.isEmpty(id)) {
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index 4113ac7..9e811a6 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -38,15 +38,46 @@
  * </li>
  * <li>
  * After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
- * CancellationSignal, LayoutResultCallback, Bundle)}, you may get a call to
- * {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, WriteResultCallback)}
- * asking you to write a PDF file with the content for specific pages.
+ * CancellationSignal, LayoutResultCallback, Bundle)}, you <strong>may</strong> get
+ * a call to {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
+ * WriteResultCallback)} asking you to write a PDF file with the content for
+ * specific pages.
  * </li>
  * <li>
  * Finally, you will receive a call to {@link #onFinish()}. You can use this
  * callback to release resources allocated in {@link #onStart()}.
  * </li>
  * </ul>
+ * <p>
+ * The {@link #onStart()} callback is always the first call you will receive and
+ * is useful for doing one time setup or resource allocation before printing. You
+ * will not receive a subsequent call here.
+ * </p>
+ * <p>
+ * The {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
+ * LayoutResultCallback, Bundle)} callback requires that you layout the content
+ * based on the current {@link PrintAttributes}. The execution of this method is
+ * not considered completed until you invoke one of the methods on the passed in
+ * callback instance. Hence, you will not receive a subsequent call to any other
+ * method of this class until the execution of this method is complete by invoking
+ * one of the callback methods.
+ * </p>
+ * <p>
+ * The {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
+ * WriteResultCallback)} requires that you render and write the content of some
+ * pages to the provided destination. The execution of this method is not
+ * considered complete until you invoke one of the methods on the passed in
+ * callback instance. Hence, you will not receive a subsequent call to any other
+ * method of this class until the execution of this method is complete by invoking
+ * one of the callback methods. You will never receive a sequence of one or more
+ * calls to this method without a previous call to {@link #onLayout(PrintAttributes,
+ * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)}.
+ * </p>
+ * <p>
+ * The {@link #onFinish()} callback is always the last call you will receive and
+ * is useful for doing one time cleanup or resource deallocation after printing.
+ * You will not receive a subsequent call here.
+ * </p>
  * </p>
  * <h3>Implementation</h3>
  * <p>
@@ -54,7 +85,11 @@
  * of the work on an arbitrary thread. For example, if the printed content
  * does not depend on the UI state, i.e. on what is shown on the screen, then
  * you can offload the entire work on a dedicated thread, thus making your
- * application interactive while the print work is being performed.
+ * application interactive while the print work is being performed. Note that
+ * while your activity is covered by the system print UI and a user cannot
+ * interact with it, doing the printing work on the main application thread
+ * may affect the performance of your other application components as they
+ * are also executed on that thread.
  * </p>
  * <p>
  * You can also do work on different threads, for example if you print UI
@@ -64,7 +99,7 @@
  * This will ensure that the UI does not change while you are laying out the
  * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
  * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
- * thread. This will ensure that the UI is frozen for the minimal amount of
+ * thread. This will ensure that the main thread is busy for a minimal amount of
  * time. Also this assumes that you will generate the printed content in
  * {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
  * LayoutResultCallback, Bundle)} which is not mandatory. If you use multiple
@@ -76,6 +111,12 @@
     /**
      * Extra: mapped to a boolean value that is <code>true</code> if
      * the current layout is for a print preview, <code>false</code> otherwise.
+     * This extra is provided in the {@link Bundle} argument of the {@link
+     * #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
+     * LayoutResultCallback, Bundle)} callback.
+     *
+     * @see #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
+     * LayoutResultCallback, Bundle)
      */
     public static final String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW";
 
@@ -95,17 +136,20 @@
      * After you are done laying out, you <strong>must</strong> invoke: {@link
      * LayoutResultCallback#onLayoutFinished(PrintDocumentInfo, boolean)} with
      * the last argument <code>true</code> or <code>false</code> depending on
-     * whether the layout changed the content or not, respectively; and {@link
-     * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred.
-     * Note that you must call one of the methods of the given callback.
+     * whether the layout changed the content or not, respectively; or {@link
+     * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred;
+     * or {@link LayoutResultCallback#onLayoutCancelled()} if layout was
+     * cancelled in a response to a cancellation request via the passed in
+     * {@link CancellationSignal}. Note that you <strong>must</strong> call one of
+     * the methods of the given callback for this method to be considered complete.
      * </p>
      * <p>
      * <strong>Note:</strong> If the content is large and a layout will be
      * performed, it is a good practice to schedule the work on a dedicated
      * thread and register an observer in the provided {@link
      * CancellationSignal} upon invocation of which you should stop the
-     * layout. The cancellation callback will not be made on the main
-     * thread.
+     * layout. The cancellation callback <strong>will not</strong> be made on
+     * the main thread.
      * </p>
      *
      * @param oldAttributes The old print attributes.
@@ -128,10 +172,12 @@
      * on the main thread.
      *<p>
      * After you are done writing, you should close the file descriptor and
-     * invoke {@link WriteResultCallback #onWriteFinished(PageRange[]), if writing
+     * invoke {@link WriteResultCallback#onWriteFinished(PageRange[])}, if writing
      * completed successfully; or {@link WriteResultCallback#onWriteFailed(
-     * CharSequence)}, if an error occurred. Note that you must call one of
-     * the methods of the given callback.
+     * CharSequence)}, if an error occurred; or {@link WriteResultCallback#onWriteCancelled()},
+     * if writing was cancelled in a response to a cancellation request via the passed
+     * in {@link CancellationSignal}. Note that you <strong>must</strong> call one of
+     * the methods of the given callback for this method to be considered complete.
      * </p>
      * <p>
      * <strong>Note:</strong> If the printed content is large, it is a good
@@ -178,7 +224,8 @@
         /**
          * Notifies that all the data was written.
          *
-         * @param pages The pages that were written. Cannot be null or empty.
+         * @param pages The pages that were written. Cannot be <code>null</code>
+         * or empty.
          */
         public void onWriteFinished(PageRange[] pages) {
             /* do nothing - stub */
@@ -187,7 +234,8 @@
         /**
          * Notifies that an error occurred while writing the data.
          *
-         * @param error Error message. May be null if error is unknown.
+         * @param error The <strong>localized</strong> error message.
+         * shown to the user. May be <code>null</code> if error is unknown.
          */
         public void onWriteFailed(CharSequence error) {
             /* do nothing - stub */
@@ -218,7 +266,7 @@
         /**
          * Notifies that the layout finished and whether the content changed.
          *
-         * @param info An info object describing the document. Cannot be null.
+         * @param info An info object describing the document. Cannot be <code>null</code>.
          * @param changed Whether the layout changed.
          *
          * @see PrintDocumentInfo
@@ -230,7 +278,8 @@
         /**
          * Notifies that an error occurred while laying out the document.
          *
-         * @param error Error message. May be null if error is unknown.
+         * @param error The <strong>localized</strong> error message.
+         * shown to the user. May be <code>null</code> if error is unknown.
          */
         public void onLayoutFailed(CharSequence error) {
             /* do nothing - stub */
diff --git a/core/java/android/print/PrintDocumentInfo.java b/core/java/android/print/PrintDocumentInfo.java
index b721ef4..928be6c 100644
--- a/core/java/android/print/PrintDocumentInfo.java
+++ b/core/java/android/print/PrintDocumentInfo.java
@@ -21,12 +21,56 @@
 import android.text.TextUtils;
 
 /**
- * This class encapsulates information about a printed document.
+ * This class encapsulates information about a document for printing
+ * purposes. This meta-data is used by the platform and print services,
+ * components that interact with printers. For example, this class
+ * contains the number of pages contained in the document it describes and
+ * this number of pages is shown to the user allowing him/her to select
+ * the range to print. Also a print service may optimize the printing
+ * process based on the content type, such as document or photo.
+ * <p>
+ * Instances of this class are created by the printing application and
+ * passed to the {@link PrintDocumentAdapter.LayoutResultCallback#onLayoutFinished(
+ * PrintDocumentInfo, boolean) PrintDocumentAdapter.LayoutResultCallback.onLayoutFinished(
+ * PrintDocumentInfo, boolean)} callback after successfully laying out the
+ * content which is performed in {@link PrintDocumentAdapter#onLayout(PrintAttributes,
+ * PrintAttributes, android.os.CancellationSignal, PrintDocumentAdapter.LayoutResultCallback,
+ * android.os.Bundle) PrintDocumentAdapter.onLayout(PrintAttributes,
+ * PrintAttributes, android.os.CancellationSignal,
+ * PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle)}.
+ * </p>
+ * <p>
+ * An example usage looks like this:
+ * <pre>
+ *
+ * . . .
+ *
+ * public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
+ *         CancellationSignal cancellationSignal, LayoutResultCallback callback,
+ *         Bundle metadata) {
+ *
+ *        // Assume the app defined a LayoutResult class which contains
+ *        // the layout result data and that the content is a document.
+ *        LayoutResult result = doSomeLayoutWork();
+ *
+ *        PrintDocumentInfo info = new PrintDocumentInfo
+ *                .Builder("printed_file.pdf")
+ *                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+ *                .setPageCount(result.getPageCount())
+ *                .build();
+ *
+ *       callback.onLayoutFinished(info, result.getContentChanged());
+ *   }
+ *
+ *   . . .
+ *
+ * </pre>
+ * </p>
  */
 public final class PrintDocumentInfo implements Parcelable {
 
     /**
-     * Constant for unknown page count..
+     * Constant for unknown page count.
      */
     public static final int PAGE_COUNT_UNKNOWN = -1;
 
@@ -37,11 +81,23 @@
 
     /**
      * Content type: document.
+     * <p>
+     * A print service may use normal paper to print the content instead
+     * of dedicated photo paper. Also it may use a lower quality printing
+     * process as the content is not as sensitive to print quality variation
+     * as a photo is.
+     * </p>
      */
     public static final int CONTENT_TYPE_DOCUMENT = 0;
 
     /**
      * Content type: photo.
+     * <p>
+     * A print service may use dedicated photo paper to print the content
+     * instead of normal paper. Also it may use a higher quality printing
+     * process as the content is more sensitive to print quality variation
+     * than a document.
+     * </p>
      */
     public static final int CONTENT_TYPE_PHOTO = 1;
 
@@ -82,7 +138,8 @@
     }
 
     /**
-     * Gets the document name.
+     * Gets the document name. This name may be shown to
+     * the user.
      *
      * @return The document name.
      */
@@ -213,20 +270,23 @@
     }
 
     /**
-     * Builder for creating an {@link PrintDocumentInfo}.
+     * Builder for creating a {@link PrintDocumentInfo}.
      */
     public static final class Builder {
         private final PrintDocumentInfo mPrototype;
 
         /**
          * Constructor.
+         * 
          * <p>
-         * The values of the relevant properties are initialized with default
-         * values. Please refer to the documentation of the individual setters
-         * for information about the default values.
+         * The values of the relevant properties are initialized with defaults.
+         * Please refer to the documentation of the individual setters for
+         * information about the default values.
          * </p>
          *
-         * @param name The document name. Cannot be empty. 
+         * @param name The document name which may be shown to the user and
+         * is the file name if the content it describes is saved as a PDF.
+         * Cannot be empty. 
          */
         public Builder(String name) {
             if (TextUtils.isEmpty(name)) {
diff --git a/core/java/android/print/PrintJob.java b/core/java/android/print/PrintJob.java
index 535ae43..0abe2193 100644
--- a/core/java/android/print/PrintJob.java
+++ b/core/java/android/print/PrintJob.java
@@ -17,8 +17,13 @@
 package android.print;
 
 /**
- * This class represents a print job from the perspective of
- * an application.
+ * This class represents a print job from the perspective of an
+ * application. It contains behavior methods for performing operations
+ * on it as well as methods for querying its state. A snapshot of the
+ * print job state is represented by the {@link PrintJobInfo} class.
+ * The state of a print job may change over time. An application receives
+ * instances of this class when creating a print job or querying for
+ * its print jobs.
  */
 public final class PrintJob {
 
@@ -145,11 +150,12 @@
     /**
      * Gets whether this print job is failed. Such a print job is
      * not successfully printed due to an error. You can request
-     * a restart via {@link #restart()}.
+     * a restart via {@link #restart()} or cancel via {@link #cancel()}.
      *
      * @return Whether the print job is failed.
      *
      * @see #restart()
+     * @see #cancel()
      */
     public boolean isFailed() {
         return getInfo().getState() == PrintJobInfo.STATE_FAILED;
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index c6f0a68..c2f190d 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -22,7 +22,10 @@
 import java.util.Arrays;
 
 /**
- * This class represents the description of a print job.
+ * This class represents the description of a print job. The print job
+ * state includes properties such as its id, print attributes used for
+ * generating the content, and so on. Note that the print jobs state may
+ * change over time and this class represents a snapshot of this state.
  */
 public final class PrintJobInfo implements Parcelable {
 
@@ -93,7 +96,7 @@
     public static final int STATE_BLOCKED = 4;
 
     /**
-     * Print job state: The print job was successfully printed.
+     * Print job state: The print job is successfully printed.
      * This is a terminal state.
      * <p>
      * Next valid states: None
@@ -103,15 +106,14 @@
 
     /**
      * Print job state: The print job was printing but printing failed.
-     * This is a terminal state.
      * <p>
-     * Next valid states: None
+     * Next valid states: {@link #STATE_CANCELED}, {@link #STATE_STARTED}
      * </p>
      */
     public static final int STATE_FAILED = 6;
 
     /**
-     * Print job state: The print job was canceled.
+     * Print job state: The print job is canceled.
      * This is a terminal state.
      * <p>
      * Next valid states: None
@@ -297,6 +299,14 @@
      * Gets the current job state.
      *
      * @return The job state.
+     *
+     * @see #STATE_CREATED
+     * @see #STATE_QUEUED
+     * @see #STATE_STARTED
+     * @see #STATE_COMPLETED
+     * @see #STATE_BLOCKED
+     * @see #STATE_FAILED
+     * @see #STATE_CANCELED
      */
     public int getState() {
         return mState;
@@ -611,7 +621,7 @@
          * Constructor.
          *
          * @param prototype Prototype to use as a starting point.
-         * Can be null.
+         * Can be <code>null</code>.
          */
         public Builder(PrintJobInfo prototype) {
             mPrototype = (prototype != null)
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index dbd8278..bbfc307 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -16,6 +16,8 @@
 
 package android.print;
 
+import android.app.Activity;
+import android.app.Application.ActivityLifecycleCallbacks;
 import android.content.Context;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
@@ -53,6 +55,49 @@
  * PrintManager printManager =
  *         (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
  * </pre>
+ * 
+ * <h3>Print mechanics</h3>
+ * <p>
+ * The key idea behind printing on the platform is that the content to be printed
+ * should be laid out for the currently selected print options resulting in an
+ * optimized output and higher user satisfaction. To achieve this goal the platform
+ * declares a contract that the printing application has to follow which is defined
+ * by the {@link PrintDocumentAdapter} class. At a higher level the contract is that
+ * when the user selects some options from the print UI that may affect the way
+ * content is laid out, for example page size, the application receives a callback
+ * allowing it to layout the content to better fit these new constraints. After a
+ * layout pass the system may ask the application to render one or more pages one
+ * or more times. For example, an application may produce a single column list for
+ * smaller page sizes and a multi-column table for larger page sizes.
+ * </p>
+ * <h3>Print jobs</h3>
+ * <p>
+ * Print jobs are started by calling the {@link #print(String, PrintDocumentAdapter,
+ * PrintAttributes)} from an activity which results in bringing up the system print
+ * UI. Once the print UI is up, when the user changes a selected print option that
+ * affects the way content is laid out the system starts to interact with the
+ * application following the mechanics described the section above.
+ * </p>
+ * <p>
+ * Print jobs can be in {@link PrintJobInfo#STATE_CREATED created}, {@link
+ * PrintJobInfo#STATE_QUEUED queued}, {@link PrintJobInfo#STATE_STARTED started},
+ * {@link PrintJobInfo#STATE_BLOCKED blocked}, {@link PrintJobInfo#STATE_COMPLETED
+ * completed}, {@link PrintJobInfo#STATE_FAILED failed}, and {@link
+ * PrintJobInfo#STATE_CANCELED canceled} state. Print jobs are stored in dedicated
+ * system spooler until they are handled which is they are cancelled or completed.
+ * Active print jobs, ones that are not cancelled or completed, are considered failed
+ * if the device reboots as the new boot may be after a very long time. The user may
+ * choose to restart such print jobs. Once a print job is queued all relevant content
+ * is stored in the system spooler and its lifecycle becomes detached from this of
+ * the application that created it.
+ * </p>
+ * <p>
+ * An applications can query the print spooler for current print jobs it created
+ * but not print jobs created by other applications.
+ * </p>
+ *
+ * @see PrintJob
+ * @see PrintJobInfo
  */
 public final class PrintManager {
 
@@ -290,20 +335,54 @@
     /**
      * Creates a print job for printing a {@link PrintDocumentAdapter} with
      * default print attributes.
-     * 
-     * @param printJobName A name for the new print job.
+     * <p>
+     * Calling this method brings the print UI allowing the user to customize
+     * the print job and returns a {@link PrintJob} object without waiting for the
+     * user to customize or confirm the print job. The returned print job instance
+     * is in a {@link PrintJobInfo#STATE_CREATED created} state.
+     * <p>
+     * This method can be called only from an {@link Activity}. The rationale is that
+     * printing from a service will create an inconsistent user experience as the print
+     * UI would appear without any context.
+     * </p>
+     * <p>
+     * Also the passed in {@link PrintDocumentAdapter} will be considered invalid if
+     * your activity is finished. The rationale is that once the activity that
+     * initiated printing is finished, the provided adapter may be in an inconsistent
+     * state as it may depend on the UI presented by the activity.
+     * </p>
+     * <p>
+     * The default print attributes are a hint to the system how the data is to
+     * be printed. For example, a photo editor may look at the photo aspect ratio
+     * to determine the default orientation and provide a hint whether the printing
+     * should be in portrait or landscape. The system will do a best effort to
+     * selected the hinted options in the print dialog, given the current printer
+     * supports them.
+     * </p>
+     *
+     * @param printJobName A name for the new print job which is shown to the user.
      * @param documentAdapter An adapter that emits the document to print.
-     * @param attributes The default print job attributes.
+     * @param attributes The default print job attributes or <code>null</code>.
      * @return The created print job on success or null on failure.
+     * @throws IllegalStateException If not called from an {@link Activity}.
+     * @throws IllegalArgumentException If the print job name is empty or the
+     * document adapter is null.
+     *
      * @see PrintJob
      */
     public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter,
             PrintAttributes attributes) {
-        if (TextUtils.isEmpty(printJobName)) {
-            throw new IllegalArgumentException("priintJobName cannot be empty");
+        if (!(mContext instanceof Activity)) {
+            throw new IllegalStateException("Can print only from an activity");
         }
-        PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(documentAdapter,
-                mContext.getMainLooper());
+        if (TextUtils.isEmpty(printJobName)) {
+            throw new IllegalArgumentException("printJobName cannot be empty");
+        }
+        if (documentAdapter == null) {
+            throw new IllegalArgumentException("documentAdapter cannot be null");
+        }
+        PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(
+                (Activity) mContext, documentAdapter);
         try {
             Bundle result = mService.print(printJobName, delegate,
                     attributes, mContext.getPackageName(), mAppId, mUserId);
@@ -369,17 +448,21 @@
         return new PrinterDiscoverySession(mService, mContext, mUserId);
     }
 
-    private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub {
+    private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub
+            implements ActivityLifecycleCallbacks {
 
         private final Object mLock = new Object();
 
         private CancellationSignal mLayoutOrWriteCancellation;
 
-        private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK -
-                                                       // cleared in finish()
+        private Activity mActivity; // Strong reference OK - cleared in finish()
+
+        private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in finish
 
         private Handler mHandler; // Strong reference OK - cleared in finish()
 
+        private IPrintDocumentAdapterObserver mObserver; // Strong reference OK - cleared in finish
+
         private LayoutSpec mLastLayoutSpec;
 
         private WriteSpec mLastWriteSpec;
@@ -390,16 +473,39 @@
         private boolean mFinishRequested;
         private boolean mFinished;
 
-        public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) {
+        private boolean mDestroyed;
+
+        public PrintDocumentAdapterDelegate(Activity activity,
+                PrintDocumentAdapter documentAdapter) {
+            mActivity = activity;
             mDocumentAdapter = documentAdapter;
-            mHandler = new MyHandler(looper);
+            mHandler = new MyHandler(mActivity.getMainLooper());
+            mActivity.getApplication().registerActivityLifecycleCallbacks(this);
+        }
+
+        @Override
+        public void setObserver(IPrintDocumentAdapterObserver observer) {
+            final boolean destroyed;
+            synchronized (mLock) {
+                if (!mDestroyed) {
+                    mObserver = observer;
+                }
+                destroyed = mDestroyed;
+            }
+            if (destroyed) {
+                try {
+                    observer.onDestroy();
+                } catch (RemoteException re) {
+                    Log.e(LOG_TAG, "Error announcing destroyed state", re);
+                }
+            }
         }
 
         @Override
         public void start() {
             synchronized (mLock) {
-                // Started or finished - nothing to do.
-                if (mStartReqeusted || mFinishRequested) {
+                // Started called or finish called or destroyed - nothing to do.
+                if (mStartReqeusted || mFinishRequested || mDestroyed) {
                     return;
                 }
 
@@ -412,71 +518,85 @@
         @Override
         public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
                 ILayoutResultCallback callback, Bundle metadata, int sequence) {
+            final boolean destroyed;
             synchronized (mLock) {
-                // Start not called or finish called - nothing to do.
-                if (!mStartReqeusted || mFinishRequested) {
-                    return;
+                destroyed = mDestroyed;
+                // If start called and not finished called and not destroyed - do some work.
+                if (mStartReqeusted && !mFinishRequested && !mDestroyed) {
+                    // Layout cancels write and overrides layout.
+                    if (mLastWriteSpec != null) {
+                        IoUtils.closeQuietly(mLastWriteSpec.fd);
+                        mLastWriteSpec = null;
+                    }
+
+                    mLastLayoutSpec = new LayoutSpec();
+                    mLastLayoutSpec.callback = callback;
+                    mLastLayoutSpec.oldAttributes = oldAttributes;
+                    mLastLayoutSpec.newAttributes = newAttributes;
+                    mLastLayoutSpec.metadata = metadata;
+                    mLastLayoutSpec.sequence = sequence;
+
+                    // Cancel the previous cancellable operation.When the
+                    // cancellation completes we will do the pending work.
+                    if (cancelPreviousCancellableOperationLocked()) {
+                        return;
+                    }
+
+                    doPendingWorkLocked();
                 }
-
-                // Layout cancels write and overrides layout.
-                if (mLastWriteSpec != null) {
-                    IoUtils.closeQuietly(mLastWriteSpec.fd);
-                    mLastWriteSpec = null;
+            }
+            if (destroyed) {
+                try {
+                    callback.onLayoutFailed(null, sequence);
+                } catch (RemoteException re) {
+                    Log.i(LOG_TAG, "Error notifying for cancelled layout", re);
                 }
-
-                mLastLayoutSpec = new LayoutSpec();
-                mLastLayoutSpec.callback = callback;
-                mLastLayoutSpec.oldAttributes = oldAttributes;
-                mLastLayoutSpec.newAttributes = newAttributes;
-                mLastLayoutSpec.metadata = metadata;
-                mLastLayoutSpec.sequence = sequence;
-
-                // Cancel the previous cancellable operation.When the
-                // cancellation completes we will do the pending work.
-                if (cancelPreviousCancellableOperationLocked()) {
-                    return;
-                }
-
-                doPendingWorkLocked();
             }
         }
 
         @Override
         public void write(PageRange[] pages, ParcelFileDescriptor fd,
                 IWriteResultCallback callback, int sequence) {
+            final boolean destroyed;
             synchronized (mLock) {
-                // Start not called or finish called - nothing to do.
-                if (!mStartReqeusted || mFinishRequested) {
-                    return;
+                destroyed = mDestroyed;
+                // If start called and not finished called and not destroyed - do some work.
+                if (mStartReqeusted && !mFinishRequested && !mDestroyed) {
+                    // Write cancels previous writes.
+                    if (mLastWriteSpec != null) {
+                        IoUtils.closeQuietly(mLastWriteSpec.fd);
+                        mLastWriteSpec = null;
+                    }
+
+                    mLastWriteSpec = new WriteSpec();
+                    mLastWriteSpec.callback = callback;
+                    mLastWriteSpec.pages = pages;
+                    mLastWriteSpec.fd = fd;
+                    mLastWriteSpec.sequence = sequence;
+
+                    // Cancel the previous cancellable operation.When the
+                    // cancellation completes we will do the pending work.
+                    if (cancelPreviousCancellableOperationLocked()) {
+                        return;
+                    }
+
+                    doPendingWorkLocked();
                 }
-
-                // Write cancels previous writes.
-                if (mLastWriteSpec != null) {
-                    IoUtils.closeQuietly(mLastWriteSpec.fd);
-                    mLastWriteSpec = null;
+            }
+            if (destroyed) {
+                try {
+                    callback.onWriteFailed(null, sequence);
+                } catch (RemoteException re) {
+                    Log.i(LOG_TAG, "Error notifying for cancelled write", re);
                 }
-
-                mLastWriteSpec = new WriteSpec();
-                mLastWriteSpec.callback = callback;
-                mLastWriteSpec.pages = pages;
-                mLastWriteSpec.fd = fd;
-                mLastWriteSpec.sequence = sequence;
-
-                // Cancel the previous cancellable operation.When the
-                // cancellation completes we will do the pending work.
-                if (cancelPreviousCancellableOperationLocked()) {
-                    return;
-                }
-
-                doPendingWorkLocked();
             }
         }
 
         @Override
         public void finish() {
             synchronized (mLock) {
-                // Start not called or finish called - nothing to do.
-                if (!mStartReqeusted || mFinishRequested) {
+                // Start not called or finish called or destroyed - nothing to do.
+                if (!mStartReqeusted || mFinishRequested || mDestroyed) {
                     return;
                 }
 
@@ -495,15 +615,78 @@
             }
         }
 
+        @Override
+        public void onActivityPaused(Activity activity) {
+            /* do nothing */
+        }
+
+        @Override
+        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+            /* do nothing */
+        }
+
+        @Override
+        public void onActivityStarted(Activity activity) {
+            /* do nothing */
+        }
+
+        @Override
+        public void onActivityResumed(Activity activity) {
+            /* do nothing */
+        }
+
+        @Override
+        public void onActivityStopped(Activity activity) {
+            /* do nothing */
+        }
+
+        @Override
+        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+            /* do nothing */
+        }
+
+        @Override
+        public void onActivityDestroyed(Activity activity) {
+            // We really care only if the activity is being destroyed to
+            // notify the the print spooler so it can close the print dialog.
+            // Note the the spooler has a death recipient that observes if
+            // this process gets killed so we cover the case of onDestroy not
+            // being called due to this process being killed to reclaim memory.
+            final IPrintDocumentAdapterObserver observer;
+            synchronized (mLock) {
+                if (activity == mActivity) {
+                    mDestroyed = true;
+                    observer = mObserver;
+                    clearLocked();
+                } else {
+                    observer = null;
+                    activity = null;
+                }
+            }
+            if (observer != null) {
+                activity.getApplication().unregisterActivityLifecycleCallbacks(
+                        PrintDocumentAdapterDelegate.this);
+                try {
+                    observer.onDestroy();
+                } catch (RemoteException re) {
+                    Log.e(LOG_TAG, "Error announcing destroyed state", re);
+                }
+            }
+        }
+
         private boolean isFinished() {
             return mDocumentAdapter == null;
         }
 
-        private void doFinish() {
+        private void clearLocked() {
+            mActivity = null;
             mDocumentAdapter = null;
             mHandler = null;
-            synchronized (mLock) {
-                mLayoutOrWriteCancellation = null;
+            mLayoutOrWriteCancellation = null;
+            mLastLayoutSpec = null;
+            if (mLastWriteSpec != null) {
+                IoUtils.closeQuietly(mLastWriteSpec.fd);
+                mLastWriteSpec = null;
             }
         }
 
@@ -564,63 +747,81 @@
                 }
                 switch (message.what) {
                     case MSG_START: {
-                        mDocumentAdapter.onStart();
-                    }
-                        break;
+                        final PrintDocumentAdapter adapter;
+                        synchronized (mLock) {
+                            adapter = mDocumentAdapter;
+                        }
+                        if (adapter != null) {
+                            adapter.onStart();
+                        }
+                    } break;
 
                     case MSG_LAYOUT: {
+                        final PrintDocumentAdapter adapter;
                         final CancellationSignal cancellation;
                         final LayoutSpec layoutSpec;
 
                         synchronized (mLock) {
+                            adapter = mDocumentAdapter;
                             layoutSpec = mLastLayoutSpec;
                             mLastLayoutSpec = null;
                             cancellation = new CancellationSignal();
                             mLayoutOrWriteCancellation = cancellation;
                         }
 
-                        if (layoutSpec != null) {
+                        if (layoutSpec != null && adapter != null) {
                             if (DEBUG) {
                                 Log.i(LOG_TAG, "Performing layout");
                             }
-                            mDocumentAdapter.onLayout(layoutSpec.oldAttributes,
+                            adapter.onLayout(layoutSpec.oldAttributes,
                                     layoutSpec.newAttributes, cancellation,
                                     new MyLayoutResultCallback(layoutSpec.callback,
                                             layoutSpec.sequence), layoutSpec.metadata);
                         }
-                    }
-                        break;
+                    } break;
 
                     case MSG_WRITE: {
+                        final PrintDocumentAdapter adapter;
                         final CancellationSignal cancellation;
                         final WriteSpec writeSpec;
 
                         synchronized (mLock) {
+                            adapter = mDocumentAdapter;
                             writeSpec = mLastWriteSpec;
                             mLastWriteSpec = null;
                             cancellation = new CancellationSignal();
                             mLayoutOrWriteCancellation = cancellation;
                         }
 
-                        if (writeSpec != null) {
+                        if (writeSpec != null && adapter != null) {
                             if (DEBUG) {
                                 Log.i(LOG_TAG, "Performing write");
                             }
-                            mDocumentAdapter.onWrite(writeSpec.pages, writeSpec.fd,
+                            adapter.onWrite(writeSpec.pages, writeSpec.fd,
                                     cancellation, new MyWriteResultCallback(writeSpec.callback,
                                             writeSpec.fd, writeSpec.sequence));
                         }
-                    }
-                        break;
+                    } break;
 
                     case MSG_FINISH: {
                         if (DEBUG) {
                             Log.i(LOG_TAG, "Performing finish");
                         }
-                        mDocumentAdapter.onFinish();
-                        doFinish();
-                    }
-                        break;
+                        final PrintDocumentAdapter adapter;
+                        final Activity activity;
+                        synchronized (mLock) {
+                            adapter = mDocumentAdapter;
+                            activity = mActivity;
+                            clearLocked();
+                        }
+                        if (adapter != null) {
+                            adapter.onFinish();
+                        }
+                        if (activity != null) {
+                            activity.getApplication().unregisterActivityLifecycleCallbacks(
+                                    PrintDocumentAdapterDelegate.this);
+                        }
+                    } break;
 
                     default: {
                         throw new IllegalArgumentException("Unknown message: "
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index df51ec1..b615600 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -24,10 +24,17 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 /**
- * This class represents the capabilities of a printer.
+ * This class represents the capabilities of a printer. Instances
+ * of this class are created by a print service to report the
+ * capabilities of a printer it manages. The capabilities of a
+ * printer specify how it can print content. For example, what
+ * are the media sizes supported by the printer, what are the
+ * minimal margins of the printer based on its technical design,
+ * etc.
  */
 public final class PrinterCapabilitiesInfo implements Parcelable {
     /**
@@ -112,7 +119,7 @@
      * @return The media sizes.
      */
     public List<MediaSize> getMediaSizes() {
-        return mMediaSizes;
+        return Collections.unmodifiableList(mMediaSizes);
     }
 
     /**
@@ -121,7 +128,7 @@
      * @return The resolutions.
      */
     public List<Resolution> getResolutions() {
-        return mResolutions;
+        return Collections.unmodifiableList(mResolutions);
     }
 
     /**
@@ -135,9 +142,9 @@
     }
 
     /**
-     * Gets the supported color modes.
+     * Gets the bit mask of supported color modes.
      *
-     * @return The color modes.
+     * @return The bit mask of supported color modes.
      *
      * @see PrintAttributes#COLOR_MODE_COLOR
      * @see PrintAttributes#COLOR_MODE_MONOCHROME
@@ -355,9 +362,10 @@
     }
 
     /**
-     * Builder for creating of a {@link PrinterInfo}. This class is responsible
-     * to enforce that all required attributes have at least one default value.
-     * In other words, this class creates only well-formed {@link PrinterInfo}s.
+     * Builder for creating of a {@link PrinterCapabilitiesInfo}. This class is
+     * responsible to enforce that all required attributes have at least one
+     * default value. In other words, this class creates only well-formed {@link
+     * PrinterCapabilitiesInfo}s.
      * <p>
      * Look at the individual methods for a reference whether a property is
      * required or if it is optional.
@@ -369,9 +377,9 @@
         /**
          * Creates a new instance.
          *
-         * @param printerId The printer id. Cannot be null.
+         * @param printerId The printer id. Cannot be <code>null</code>.
          *
-         * @throws IllegalArgumentException If the printer id is null.
+         * @throws IllegalArgumentException If the printer id is <code>null</code>.
          */
         public Builder(PrinterId printerId) {
             if (printerId == null) {
@@ -492,7 +500,7 @@
 
         /**
          * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
-         * required properties have need specified. See individual methods
+         * required properties have been specified. See individual methods
          * in this class for reference about required attributes.
          *
          * @return A new {@link PrinterCapabilitiesInfo}.
@@ -521,7 +529,7 @@
             if (mPrototype.mMinMargins == null) {
                 throw new IllegalArgumentException("margins cannot be null");
             }
-            return new PrinterCapabilitiesInfo(mPrototype);
+            return mPrototype;
         }
 
         private void throwIfDefaultAlreadySpecified(int propertyIndex) {
diff --git a/core/java/android/print/PrinterInfo.java b/core/java/android/print/PrinterInfo.java
index ad79a38..7fcc81f 100644
--- a/core/java/android/print/PrinterInfo.java
+++ b/core/java/android/print/PrinterInfo.java
@@ -21,7 +21,12 @@
 import android.text.TextUtils;
 
 /**
- * This class represents the description of a printer.
+ * This class represents the description of a printer. Instances of
+ * this class are created by print services to report to the system
+ * the printers they manage. The information of this class has two
+ * major components, printer properties such as name, id, status,
+ * description and printer capabilities which describe the various
+ * print modes a printer supports such as media sizes, margins, etc.
  */
 public final class PrinterInfo implements Parcelable {
 
@@ -96,6 +101,10 @@
      * Gets the printer status.
      *
      * @return The status.
+     *
+     * @see #STATUS_BUSY
+     * @see #STATUS_IDLE
+     * @see #STATUS_UNAVAILABLE
      */
     public int getStatus() {
         return mStatus;
@@ -216,6 +225,8 @@
          * @param printerId The printer id. Cannot be null.
          * @param name The printer name. Cannot be empty.
          * @param status The printer status. Must be a valid status.
+         * @throws IllegalArgumentException If the printer id is null, or the
+         * printer name is empty or the status is not a valid one.
          */
         public Builder(PrinterId printerId, String name, int status) {
             if (printerId == null) {
@@ -259,7 +270,8 @@
         }
 
         /**
-         * Sets the printer name.
+         * Sets the <strong>localized</strong> printer name which
+         * is shown to the user
          *
          * @param name The name.
          * @return This builder.
@@ -270,7 +282,8 @@
         }
 
         /**
-         * Sets the printer description.
+         * Sets the <strong>localized</strong> printer description
+         * which is shown to the user
          *
          * @param description The description.
          * @return This builder.
@@ -292,12 +305,12 @@
         }
 
         /**
-         * Crates a new {@link PrinterInfo}.
+         * Creates a new {@link PrinterInfo}.
          *
          * @return A new {@link PrinterInfo}.
          */
         public PrinterInfo build() {
-            return new PrinterInfo(mPrototype);
+            return mPrototype;
         }
 
         private boolean isValidStatus(int status) {
diff --git a/core/java/android/print/package.html b/core/java/android/print/package.html
new file mode 100644
index 0000000..579567d
--- /dev/null
+++ b/core/java/android/print/package.html
@@ -0,0 +1,46 @@
+<HTML>
+<BODY>
+<h3>Overview</h3>
+<p>
+Provides classes for implementing print support in applications and also contains all
+base classes and abstractions involved in printing. These base classes are also used
+by other more specialized printing related packages.
+</p>
+<p>
+The entry point for interacting with the print system is the {@link android.print.PrintManager}
+which is a system service that can be obtained from the current context. The print manager
+provides APIs for printing, querying the state of print jobs, etc.
+<p/>
+<h3>Print contract</h3>
+<p>
+An application that wants to implement printing must extend
+{@link android.print.PrintDocumentAdapter} which defines the contract between the system
+and the application.The key idea behind this adapter is that the printed content may change
+based on the selected print options, such as media size, orientation, which
+requires the content to be re-laid out. The constraints according to which the content has
+to be laid out are encapsulated in the {@link android.print.PrintAttributes} class. Once
+layout is completed the application calls back to the system passing a
+{@link android.print.PrintDocumentInfo} instance which describes the generated content. After
+the content has been laid out the application may be asked to render some pages of that content
+for preview or printing. The range of pages that have to be rendered is abstracted by the
+{@link android.print.PageRange} class.
+</p>
+<h3>Print jobs</h3>
+<p>
+A print job is represented by the {@link android.print.PrintJob} class which has behavior
+methods as well as methods for querying its state. Each print job has a unique id represented
+by the {@link android.print.PrintJobId} class and exposes APIs for obtaining a {@link
+android.print.PrintJobInfo} which is a snapshot of its state. The print job state may
+change over time.
+</p>
+<h3>Printers</h3>
+<p>
+An available printer represented by the {@link android.print.PrinterInfo} class has a
+unique id which is abstracted by the {@link android.print.PrinterId} class. The {@link
+android.print.PrinterInfo} contains printer properties such as id, name, description, status,
+and printer capabilities encapsulated in the {@link android.print.PrinterCapabilitiesInfo}
+class. Printer capabilities describe how a printer can print content, for example what are
+the supported media sizes, color modes, resolutions, etc.
+<p>
+</BODY>
+</HTML>
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index c9efb53..e35b8eb 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -76,9 +76,8 @@
  * only the system can obtain. Applications cannot use a documents provider
  * directly; they must go through {@link Intent#ACTION_OPEN_DOCUMENT} or
  * {@link Intent#ACTION_CREATE_DOCUMENT} which requires a user to actively
- * navigate and select documents. When a user selects documents through that
- * UI, the system issues narrow URI permission grants to the requesting
- * application.
+ * navigate and select documents. When a user selects documents through that UI,
+ * the system issues narrow URI permission grants to the requesting application.
  * </p>
  * <h3>Documents</h3>
  * <p>
@@ -91,8 +90,8 @@
  * <p>
  * Each document can have different capabilities, as described by
  * {@link Document#COLUMN_FLAGS}. For example, if a document can be represented
- * as a thumbnail, a provider can set {@link Document#FLAG_SUPPORTS_THUMBNAIL}
- * and implement
+ * as a thumbnail, your provider can set
+ * {@link Document#FLAG_SUPPORTS_THUMBNAIL} and implement
  * {@link #openDocumentThumbnail(String, Point, CancellationSignal)} to return
  * that thumbnail.
  * </p>
@@ -102,7 +101,7 @@
  * single document can be included in multiple directories when responding to
  * {@link #queryChildDocuments(String, String[], String)}. For example, a
  * provider might surface a single photo in multiple locations: once in a
- * directory of locations, and again in a directory of dates.
+ * directory of geographic locations, and again in a directory of dates.
  * </p>
  * <h3>Roots</h3>
  * <p>
@@ -162,7 +161,7 @@
 
     /**
      * Create a new document and return its newly generated
-     * {@link Document#COLUMN_DOCUMENT_ID}. A provider must allocate a new
+     * {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new
      * {@link Document#COLUMN_DOCUMENT_ID} to represent the document, which must
      * not change once returned.
      *
@@ -194,16 +193,17 @@
     }
 
     /**
-     * Return all roots currently provided. A provider must define at least one
-     * root to display to users, and it should avoid making network requests to
-     * keep this request fast.
+     * Return all roots currently provided. To display to users, you must define
+     * at least one root. You should avoid making network requests to keep this
+     * request fast.
      * <p>
      * Each root is defined by the metadata columns described in {@link Root},
      * including {@link Root#COLUMN_DOCUMENT_ID} which points to a directory
      * representing a tree of documents to display under that root.
      * <p>
      * If this set of roots changes, you must call {@link ContentResolver#notifyChange(Uri,
-     * android.database.ContentObserver)} to notify the system.
+     * android.database.ContentObserver, boolean)} with
+     * {@link DocumentsContract#buildRootsUri(String)} to notify the system.
      *
      * @param projection list of {@link Root} columns to put into the cursor. If
      *            {@code null} all supported columns should be included.
@@ -229,8 +229,8 @@
     }
 
     /**
-     * Return metadata for the single requested document. A provider should
-     * avoid making network requests to keep this request fast.
+     * Return metadata for the single requested document. You should avoid
+     * making network requests to keep this request fast.
      *
      * @param documentId the document to return.
      * @param projection list of {@link Document} columns to put into the
@@ -248,10 +248,17 @@
      * If your provider is cloud-based, and you have some data cached or pinned
      * locally, you may return the local data immediately, setting
      * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that
-     * your provider is still fetching additional data. Then, when the network
-     * data is available, you can call {@link ContentResolver#notifyChange(Uri,
-     * android.database.ContentObserver)} to trigger a requery and return the
-     * complete contents.
+     * you are still fetching additional data. Then, when the network data is
+     * available, you can send a change notification to trigger a requery and
+     * return the complete contents.
+     * <p>
+     * To support change notifications, you must
+     * {@link Cursor#setNotificationUri(ContentResolver, Uri)} with a relevant
+     * Uri, such as
+     * {@link DocumentsContract#buildChildDocumentsUri(String, String)}. Then
+     * you can call {@link ContentResolver#notifyChange(Uri,
+     * android.database.ContentObserver, boolean)} with that Uri to send change
+     * notifications.
      *
      * @param parentDocumentId the directory to return children for.
      * @param projection list of {@link Document} columns to put into the
@@ -289,6 +296,20 @@
      * <p>
      * Only documents may be returned; directories are not supported in search
      * results.
+     * <p>
+     * If your provider is cloud-based, and you have some data cached or pinned
+     * locally, you may return the local data immediately, setting
+     * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that
+     * you are still fetching additional data. Then, when the network data is
+     * available, you can send a change notification to trigger a requery and
+     * return the complete contents.
+     * <p>
+     * To support change notifications, you must
+     * {@link Cursor#setNotificationUri(ContentResolver, Uri)} with a relevant
+     * Uri, such as {@link DocumentsContract#buildSearchDocumentsUri(String,
+     * String, String)}. Then you can call {@link ContentResolver#notifyChange(Uri,
+     * android.database.ContentObserver, boolean)} with that Uri to send change
+     * notifications.
      *
      * @param rootId the root to search under.
      * @param query string to match documents against.
@@ -327,17 +348,14 @@
     /**
      * Open and return the requested document.
      * <p>
-     * A provider should return a reliable {@link ParcelFileDescriptor} to
+     * Your provider should return a reliable {@link ParcelFileDescriptor} to
      * detect when the remote caller has finished reading or writing the
-     * document. A provider may return a pipe or socket pair if the mode is
-     * exclusively {@link ParcelFileDescriptor#MODE_READ_ONLY} or
-     * {@link ParcelFileDescriptor#MODE_WRITE_ONLY}, but complex modes like
-     * {@link ParcelFileDescriptor#MODE_READ_WRITE} require a normal file on
-     * disk.
+     * document. You may return a pipe or socket pair if the mode is exclusively
+     * "r" or "w", but complex modes like "rw" imply a normal file on disk that
+     * supports seeking.
      * <p>
-     * If a provider blocks while downloading content, it should periodically
-     * check {@link CancellationSignal#isCanceled()} to abort abandoned open
-     * requests.
+     * If you block while downloading content, you should periodically check
+     * {@link CancellationSignal#isCanceled()} to abort abandoned open requests.
      *
      * @param documentId the document to return.
      * @param mode the mode to open with, such as 'r', 'w', or 'rw'.
@@ -359,10 +377,9 @@
      * attempting to serve from a local cache if possible. A provider should
      * never return images more than double the hinted size.
      * <p>
-     * If a provider performs expensive operations to download or generate a
-     * thumbnail, it should periodically check
-     * {@link CancellationSignal#isCanceled()} to abort abandoned thumbnail
-     * requests.
+     * If you perform expensive operations to download or generate a thumbnail,
+     * you should periodically check {@link CancellationSignal#isCanceled()} to
+     * abort abandoned thumbnail requests.
      *
      * @param documentId the document to return.
      * @param sizeHint hint of the optimal thumbnail dimensions.
diff --git a/core/java/android/transition/Scene.java b/core/java/android/transition/Scene.java
index d798abe..e1f1896 100644
--- a/core/java/android/transition/Scene.java
+++ b/core/java/android/transition/Scene.java
@@ -36,27 +36,28 @@
     private ViewGroup mSceneRoot;
     private ViewGroup mLayout; // alternative to layoutId
     Runnable mEnterAction, mExitAction;
-    private static ThreadLocal<SparseArray<Scene>> sScenes = new ThreadLocal<SparseArray<Scene>>();
 
     /**
      * Returns a Scene described by the resource file associated with the given
-     * <code>layoutId</code> parameter. If such a Scene has already been created,
-     * that same Scene will be returned. This caching of layoutId-based scenes enables
-     * sharing of common scenes between those created in code and those referenced
-     * by {@link TransitionManager} XML resource files.
+     * <code>layoutId</code> parameter. If such a Scene has already been created for
+     * the given <code>sceneRoot</code>, that same Scene will be returned.
+     * This caching of layoutId-based scenes enables sharing of common scenes
+     * between those created in code and those referenced by {@link TransitionManager}
+     * XML resource files.
      *
      * @param sceneRoot The root of the hierarchy in which scene changes
      * and transitions will take place.
      * @param layoutId The id of a standard layout resource file.
      * @param context The context used in the process of inflating
      * the layout resource.
-     * @return
+     * @return The scene for the given root and layout id
      */
     public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context) {
-        SparseArray<Scene> scenes = sScenes.get();
+        SparseArray<Scene> scenes = (SparseArray<Scene>) sceneRoot.getTag(
+                com.android.internal.R.id.scene_layoutid_cache);
         if (scenes == null) {
             scenes = new SparseArray<Scene>();
-            sScenes.set(scenes);
+            sceneRoot.setTagInternal(com.android.internal.R.id.scene_layoutid_cache, scenes);
         }
         Scene scene = scenes.get(layoutId);
         if (scene != null) {
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index dcf668b..f76e190 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -994,15 +994,7 @@
      * false otherwise
      */
     void captureValues(ViewGroup sceneRoot, boolean start) {
-        if (start) {
-            mStartValues.viewValues.clear();
-            mStartValues.idValues.clear();
-            mStartValues.itemIdValues.clear();
-        } else {
-            mEndValues.viewValues.clear();
-            mEndValues.idValues.clear();
-            mEndValues.itemIdValues.clear();
-        }
+        clearValues(start);
         if (mTargetIds.size() > 0 || mTargets.size() > 0) {
             if (mTargetIds.size() > 0) {
                 for (int i = 0; i < mTargetIds.size(); ++i) {
@@ -1055,6 +1047,23 @@
     }
 
     /**
+     * Clear valuesMaps for specified start/end state
+     *
+     * @param start true if the start values should be cleared, false otherwise
+     */
+    void clearValues(boolean start) {
+        if (start) {
+            mStartValues.viewValues.clear();
+            mStartValues.idValues.clear();
+            mStartValues.itemIdValues.clear();
+        } else {
+            mEndValues.viewValues.clear();
+            mEndValues.idValues.clear();
+            mEndValues.itemIdValues.clear();
+        }
+    }
+
+    /**
      * Recursive method which captures values for an entire view hierarchy,
      * starting at some root view. Transitions without targetIDs will use this
      * method to capture values for all possible views.
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 404709c..3bf6790 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
@@ -81,6 +82,8 @@
      * an {@link AutoTransition} instance.
      *
      * @param transition The default transition to be used for scene changes.
+     *
+     * @hide pending later changes
      */
     public void setDefaultTransition(Transition transition) {
         sDefaultTransition = transition;
@@ -92,6 +95,8 @@
      *
      * @return The current default transition.
      * @see #setDefaultTransition(Transition)
+     *
+     * @hide pending later changes
      */
     public static Transition getDefaultTransition() {
         return sDefaultTransition;
@@ -104,7 +109,7 @@
      * transition to run.
      * @param transition The transition that will play when the given scene is
      * entered. A value of null will result in the default behavior of
-     * using the {@link #getDefaultTransition() default transition} instead.
+     * using the default transition instead.
      */
     public void setTransition(Scene scene, Transition transition) {
         mSceneTransitions.put(scene, transition);
@@ -120,7 +125,7 @@
      * be run
      * @param transition The transition that will play when the given scene is
      * entered. A value of null will result in the default behavior of
-     * using the {@link #getDefaultTransition() default transition} instead.
+     * using the default transition instead.
      */
     public void setTransition(Scene fromScene, Scene toScene, Transition transition) {
         ArrayMap<Scene, Transition> sceneTransitionMap = mScenePairTransitions.get(toScene);
@@ -138,8 +143,8 @@
      *
      * @param scene The scene being entered
      * @return The Transition to be used for the given scene change. If no
-     * Transition was specified for this scene change, the {@link #getDefaultTransition()
-     * default transition} will be used instead.
+     * Transition was specified for this scene change, the default transition
+     * will be used instead.
      */
     private Transition getTransition(Scene scene) {
         Transition transition = null;
@@ -205,48 +210,91 @@
 
     private static void sceneChangeRunTransition(final ViewGroup sceneRoot,
             final Transition transition) {
-        if (transition != null) {
-            final ViewTreeObserver observer = sceneRoot.getViewTreeObserver();
-            final ViewTreeObserver.OnPreDrawListener listener =
-                    new ViewTreeObserver.OnPreDrawListener() {
-                public boolean onPreDraw() {
-                    sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
-                    sPendingTransitions.remove(sceneRoot);
-                    // Add to running list, handle end to remove it
-                    final ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
-                            getRunningTransitions();
-                    ArrayList<Transition> currentTransitions = runningTransitions.get(sceneRoot);
-                    ArrayList<Transition> previousRunningTransitions = null;
-                    if (currentTransitions == null) {
-                        currentTransitions = new ArrayList<Transition>();
-                        runningTransitions.put(sceneRoot, currentTransitions);
-                    } else if (currentTransitions.size() > 0) {
-                        previousRunningTransitions = new ArrayList<Transition>(currentTransitions);
-                    }
-                    currentTransitions.add(transition);
-                    transition.addListener(new Transition.TransitionListenerAdapter() {
-                        @Override
-                        public void onTransitionEnd(Transition transition) {
-                            ArrayList<Transition> currentTransitions =
-                                    runningTransitions.get(sceneRoot);
-                            currentTransitions.remove(transition);
-                        }
-                    });
-                    transition.captureValues(sceneRoot, false);
-                    if (previousRunningTransitions != null) {
-                        for (Transition runningTransition : previousRunningTransitions) {
-                            runningTransition.resume();
-                        }
-                    }
-                    transition.playTransition(sceneRoot);
-
-                    return true;
-                }
-            };
-            observer.addOnPreDrawListener(listener);
+        if (transition != null && sceneRoot != null) {
+            MultiListener listener = new MultiListener(transition, sceneRoot);
+            sceneRoot.addOnAttachStateChangeListener(listener);
+            sceneRoot.getViewTreeObserver().addOnPreDrawListener(listener);
         }
     }
 
+    /**
+     * This private utility class is used to listen for both OnPreDraw and
+     * OnAttachStateChange events. OnPreDraw events are the main ones we care
+     * about since that's what triggers the transition to take place.
+     * OnAttachStateChange events are also important in case the view is removed
+     * from the hierarchy before the OnPreDraw event takes place; it's used to
+     * clean up things since the OnPreDraw listener didn't get called in time.
+     */
+    private static class MultiListener implements ViewTreeObserver.OnPreDrawListener,
+            View.OnAttachStateChangeListener {
+
+        Transition mTransition;
+        ViewGroup mSceneRoot;
+
+        MultiListener(Transition transition, ViewGroup sceneRoot) {
+            mTransition = transition;
+            mSceneRoot = sceneRoot;
+        }
+
+        private void removeListeners() {
+            mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+            mSceneRoot.removeOnAttachStateChangeListener(this);
+        }
+
+        @Override
+        public void onViewAttachedToWindow(View v) {
+        }
+
+        @Override
+        public void onViewDetachedFromWindow(View v) {
+            removeListeners();
+
+            sPendingTransitions.remove(mSceneRoot);
+            ArrayList<Transition> runningTransitions = getRunningTransitions().get(mSceneRoot);
+            if (runningTransitions != null && runningTransitions.size() > 0) {
+                for (Transition runningTransition : runningTransitions) {
+                    runningTransition.resume();
+                }
+            }
+            mTransition.clearValues(true);
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            removeListeners();
+            sPendingTransitions.remove(mSceneRoot);
+            // Add to running list, handle end to remove it
+            final ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
+                    getRunningTransitions();
+            ArrayList<Transition> currentTransitions = runningTransitions.get(mSceneRoot);
+            ArrayList<Transition> previousRunningTransitions = null;
+            if (currentTransitions == null) {
+                currentTransitions = new ArrayList<Transition>();
+                runningTransitions.put(mSceneRoot, currentTransitions);
+            } else if (currentTransitions.size() > 0) {
+                previousRunningTransitions = new ArrayList<Transition>(currentTransitions);
+            }
+            currentTransitions.add(mTransition);
+            mTransition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    ArrayList<Transition> currentTransitions =
+                            runningTransitions.get(mSceneRoot);
+                    currentTransitions.remove(transition);
+                }
+            });
+            mTransition.captureValues(mSceneRoot, false);
+            if (previousRunningTransitions != null) {
+                for (Transition runningTransition : previousRunningTransitions) {
+                    runningTransition.resume();
+                }
+            }
+            mTransition.playTransition(mSceneRoot);
+
+            return true;
+        }
+    };
+
     private static void sceneChangeSetup(ViewGroup sceneRoot, Transition transition) {
 
         // Capture current values
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index dae47b8..6cda905 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -67,6 +67,14 @@
     public static final int DENSITY_XHIGH = 320;
 
     /**
+     * Intermediate density for screens that sit somewhere between
+     * {@link #DENSITY_XHIGH} (320dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
+     * This is not a density that applications should target, instead relying
+     * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
+     */
+    public static final int DENSITY_400 = 400;
+
+    /**
      * Standard quantized DPI for 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.
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f28e4b5..f1523ae 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -23,6 +23,9 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.util.Log;
+import android.util.TimeUtils;
+
+import java.io.PrintWriter;
 
 /**
  * Coordinates the timing of animations, input and drawing.
@@ -256,6 +259,15 @@
         return delayMillis <= frameDelay ? 0 : delayMillis - frameDelay;
     }
 
+    void dump(String prefix, PrintWriter writer) {
+        String innerPrefix = prefix + "  ";
+        writer.print(prefix); writer.println("Choreographer:");
+        writer.print(innerPrefix); writer.print("mFrameScheduled=");
+                writer.println(mFrameScheduled);
+        writer.print(innerPrefix); writer.print("mLastFrameTime=");
+                writer.println(TimeUtils.formatUptime(mLastFrameTimeNanos / 1000000));
+    }
+
     /**
      * Posts a callback to run on the next frame.
      * <p>
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9461068..ab93084 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -77,8 +77,10 @@
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -3458,6 +3460,12 @@
                 finishInputEvent(q);
             }
         }
+
+        void dump(String prefix, PrintWriter writer) {
+            if (mNext != null) {
+                mNext.dump(prefix, writer);
+            }
+        }
     }
 
     /**
@@ -3595,6 +3603,16 @@
             mQueueLength -= 1;
             Trace.traceCounter(Trace.TRACE_TAG_INPUT, mTraceCounter, mQueueLength);
         }
+
+        @Override
+        void dump(String prefix, PrintWriter writer) {
+            writer.print(prefix);
+            writer.print(getClass().getName());
+            writer.print(": mQueueLength=");
+            writer.println(mQueueLength);
+
+            super.dump(prefix, writer);
+        }
     }
 
     /**
@@ -5201,6 +5219,53 @@
         mView.debug();
     }
 
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        String innerPrefix = prefix + "  ";
+        writer.print(prefix); writer.println("ViewRoot:");
+        writer.print(innerPrefix); writer.print("mAdded="); writer.print(mAdded);
+                writer.print(" mRemoved="); writer.println(mRemoved);
+        writer.print(innerPrefix); writer.print("mConsumeBatchedInputScheduled=");
+                writer.println(mConsumeBatchedInputScheduled);
+        writer.print(innerPrefix); writer.print("mPendingInputEventCount=");
+                writer.println(mPendingInputEventCount);
+        writer.print(innerPrefix); writer.print("mProcessInputEventsScheduled=");
+                writer.println(mProcessInputEventsScheduled);
+        writer.print(innerPrefix); writer.print("mTraversalScheduled=");
+                writer.print(mTraversalScheduled);
+        if (mTraversalScheduled) {
+            writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")");
+        } else {
+            writer.println();
+        }
+        mFirstInputStage.dump(innerPrefix, writer);
+
+        mChoreographer.dump(prefix, writer);
+
+        writer.print(prefix); writer.println("View Hierarchy:");
+        dumpViewHierarchy(innerPrefix, writer, mView);
+    }
+
+    private void dumpViewHierarchy(String prefix, PrintWriter writer, View view) {
+        writer.print(prefix);
+        if (view == null) {
+            writer.println("null");
+            return;
+        }
+        writer.println(view.toString());
+        if (!(view instanceof ViewGroup)) {
+            return;
+        }
+        ViewGroup grp = (ViewGroup)view;
+        final int N = grp.getChildCount();
+        if (N <= 0) {
+            return;
+        }
+        prefix = prefix + "  ";
+        for (int i=0; i<N; i++) {
+            dumpViewHierarchy(prefix, writer, grp.getChildAt(i));
+        }
+    }
+
     public void dumpGfxInfo(int[] info) {
         info[0] = info[1] = 0;
         if (mView != null) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 9fc37cf..4f53c1e 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -2540,7 +2540,7 @@
 
     /**
      * Class with information if a node is a range. Use
-     * {@link RangeInfo#obtain(int, float, float, float) to get an instance.
+     * {@link RangeInfo#obtain(int, float, float, float)} to get an instance.
      */
     public static final class RangeInfo {
         private static final int MAX_POOL_SIZE = 10;
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index c440c7b..5df5811 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -45,6 +45,17 @@
 
 /**
  * This class is used to specify meta information of an input method.
+ *
+ * <p>It should be defined in an XML resource file with an {@code &lt;input-method>} element.
+ * For more information, see the guide to
+ * <a href="{@docRoot}guide/topics/text/creating-input-method.html">
+ * Creating an Input Method</a>.</p>
+ *
+ * @see InputMethodSubtype
+ *
+ * @attr ref android.R.styleable#InputMethod_settingsActivity
+ * @attr ref android.R.styleable#InputMethod_isDefault
+ * @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
  */
 public final class InputMethodInfo implements Parcelable {
     static final String TAG = "InputMethodInfo";
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 88b2977..40f95ce 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -38,9 +38,22 @@
  * the specified subtype of the designated IME directly.
  *
  * <p>It should be defined in an XML resource file of the input method with the
- * <code>&lt;subtype&gt;</code> element. For more information, see the guide to
- * <a href="{@docRoot}resources/articles/creating-input-method.html">
+ * <code>&lt;subtype&gt;</code> element, which resides within an {@code &lt;input-method>} element.
+ * For more information, see the guide to
+ * <a href="{@docRoot}guide/topics/text/creating-input-method.html">
  * Creating an Input Method</a>.</p>
+ *
+ * @see InputMethodInfo
+ *
+ * @attr ref android.R.styleable#InputMethod_Subtype_label
+ * @attr ref android.R.styleable#InputMethod_Subtype_icon
+ * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeLocale
+ * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeMode
+ * @attr ref android.R.styleable#InputMethod_Subtype_imeSubtypeExtraValue
+ * @attr ref android.R.styleable#InputMethod_Subtype_isAuxiliary
+ * @attr ref android.R.styleable#InputMethod_Subtype_overridesImplicitlyEnabledSubtype
+ * @attr ref android.R.styleable#InputMethod_Subtype_subtypeId
+ * @attr ref android.R.styleable#InputMethod_Subtype_isAsciiCapable
  */
 public final class InputMethodSubtype implements Parcelable {
     private static final String TAG = InputMethodSubtype.class.getSimpleName();
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
new file mode 100644
index 0000000..bbd3f2b
--- /dev/null
+++ b/core/java/android/webkit/CacheManager.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2006 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.webkit;
+
+import android.content.Context;
+import android.net.http.Headers;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+
+/**
+ * Manages the HTTP cache used by an application's {@link WebView} instances.
+ * @deprecated Access to the HTTP cache will be removed in a future release.
+ * @hide Since {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+ */
+// The class CacheManager provides the persistent cache of content that is
+// received over the network. The component handles parsing of HTTP headers and
+// utilizes the relevant cache headers to determine if the content should be
+// stored and if so, how long it is valid for. Network requests are provided to
+// this component and if they can not be resolved by the cache, the HTTP headers
+// are attached, as appropriate, to the request for revalidation of content. The
+// class also manages the cache size.
+//
+// CacheManager may only be used if your activity contains a WebView.
+@Deprecated
+public final class CacheManager {
+    /**
+     * Represents a resource stored in the HTTP cache. Instances of this class
+     * can be obtained by calling
+     * {@link CacheManager#getCacheFile CacheManager.getCacheFile(String, Map<String, String>))}.
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
+     */
+    @Deprecated
+    public static class CacheResult {
+        // these fields are saved to the database
+        int httpStatusCode;
+        long contentLength;
+        long expires;
+        String expiresString;
+        String localPath;
+        String lastModified;
+        String etag;
+        String mimeType;
+        String location;
+        String encoding;
+        String contentdisposition;
+        String crossDomain;
+
+        // these fields are NOT saved to the database
+        InputStream inStream;
+        OutputStream outStream;
+        File outFile;
+
+        /**
+         * Gets the status code of this cache entry.
+         *
+         * @return the status code of this cache entry
+         */
+        public int getHttpStatusCode() {
+            return httpStatusCode;
+        }
+
+        /**
+         * Gets the content length of this cache entry.
+         *
+         * @return the content length of this cache entry
+         */
+        public long getContentLength() {
+            return contentLength;
+        }
+
+        /**
+         * Gets the path of the file used to store the content of this cache
+         * entry, relative to the base directory of the cache. See
+         * {@link CacheManager#getCacheFileBaseDir CacheManager.getCacheFileBaseDir()}.
+         *
+         * @return the path of the file used to store this cache entry
+         */
+        public String getLocalPath() {
+            return localPath;
+        }
+
+        /**
+         * Gets the expiry date of this cache entry, expressed in milliseconds
+         * since midnight, January 1, 1970 UTC.
+         *
+         * @return the expiry date of this cache entry
+         */
+        public long getExpires() {
+            return expires;
+        }
+
+        /**
+         * Gets the expiry date of this cache entry, expressed as a string.
+         *
+         * @return the expiry date of this cache entry
+         *
+         */
+        public String getExpiresString() {
+            return expiresString;
+        }
+
+        /**
+         * Gets the date at which this cache entry was last modified, expressed
+         * as a string.
+         *
+         * @return the date at which this cache entry was last modified
+         */
+        public String getLastModified() {
+            return lastModified;
+        }
+
+        /**
+         * Gets the entity tag of this cache entry.
+         *
+         * @return the entity tag of this cache entry
+         */
+        public String getETag() {
+            return etag;
+        }
+
+        /**
+         * Gets the MIME type of this cache entry.
+         *
+         * @return the MIME type of this cache entry
+         */
+        public String getMimeType() {
+            return mimeType;
+        }
+
+        /**
+         * Gets the value of the HTTP 'Location' header with which this cache
+         * entry was received.
+         *
+         * @return the HTTP 'Location' header for this cache entry
+         */
+        public String getLocation() {
+            return location;
+        }
+
+        /**
+         * Gets the encoding of this cache entry.
+         *
+         * @return the encoding of this cache entry
+         */
+        public String getEncoding() {
+            return encoding;
+        }
+
+        /**
+         * Gets the value of the HTTP 'Content-Disposition' header with which
+         * this cache entry was received.
+         *
+         * @return the HTTP 'Content-Disposition' header for this cache entry
+         *
+         */
+        public String getContentDisposition() {
+            return contentdisposition;
+        }
+
+        /**
+         * Gets the input stream to the content of this cache entry, to allow
+         * content to be read. See
+         * {@link CacheManager#getCacheFile CacheManager.getCacheFile(String, Map<String, String>)}.
+         *
+         * @return an input stream to the content of this cache entry
+         */
+        public InputStream getInputStream() {
+            return inStream;
+        }
+
+        /**
+         * Gets an output stream to the content of this cache entry, to allow
+         * content to be written. See
+         * {@link CacheManager#saveCacheFile CacheManager.saveCacheFile(String, CacheResult)}.
+         *
+         * @return an output stream to the content of this cache entry
+         */
+        // Note that this is always null for objects returned by getCacheFile()!
+        public OutputStream getOutputStream() {
+            return outStream;
+        }
+
+
+        /**
+         * Sets an input stream to the content of this cache entry.
+         *
+         * @param stream an input stream to the content of this cache entry
+         */
+        public void setInputStream(InputStream stream) {
+            this.inStream = stream;
+        }
+
+        /**
+         * Sets the encoding of this cache entry.
+         *
+         * @param encoding the encoding of this cache entry
+         */
+        public void setEncoding(String encoding) {
+            this.encoding = encoding;
+        }
+
+        /**
+         * @hide
+         */
+        public void setContentLength(long contentLength) {
+            this.contentLength = contentLength;
+        }
+    }
+
+    /**
+     * Gets the base directory in which the files used to store the contents of
+     * cache entries are placed. See
+     * {@link CacheManager.CacheResult#getLocalPath CacheManager.CacheResult.getLocalPath()}.
+     *
+     * @return the base directory of the cache
+     * @deprecated This method no longer has any effect and always returns null.
+     */
+    @Deprecated
+    public static File getCacheFileBaseDir() {
+        return null;
+    }
+
+    /**
+     * Gets whether the HTTP cache is disabled.
+     *
+     * @return true if the HTTP cache is disabled
+     * @deprecated This method no longer has any effect and always returns false.
+     */
+    @Deprecated
+    public static boolean cacheDisabled() {
+        return false;
+    }
+
+    /**
+     * Starts a cache transaction. Returns true if this is the only running
+     * transaction. Otherwise, this transaction is nested inside currently
+     * running transactions and false is returned.
+     *
+     * @return true if this is the only running transaction
+     * @deprecated This method no longer has any effect and always returns false.
+     */
+    @Deprecated
+    public static boolean startCacheTransaction() {
+        return false;
+    }
+
+    /**
+     * Ends the innermost cache transaction and returns whether this was the
+     * only running transaction.
+     *
+     * @return true if this was the only running transaction
+     * @deprecated This method no longer has any effect and always returns false.
+     */
+    @Deprecated
+    public static boolean endCacheTransaction() {
+        return false;
+    }
+
+    /**
+     * Gets the cache entry for the specified URL, or null if none is found.
+     * If a non-null value is provided for the HTTP headers map, and the cache
+     * entry needs validation, appropriate headers will be added to the map.
+     * The input stream of the CacheEntry object should be closed by the caller
+     * when access to the underlying file is no longer required.
+     *
+     * @param url the URL for which a cache entry is requested
+     * @param headers a map from HTTP header name to value, to be populated
+     *                for the returned cache entry
+     * @return the cache entry for the specified URL
+     * @deprecated This method no longer has any effect and always returns null.
+     */
+    @Deprecated
+    public static CacheResult getCacheFile(String url,
+            Map<String, String> headers) {
+        return null;
+    }
+
+    /**
+     * Adds a cache entry to the HTTP cache for the specicifed URL. Also closes
+     * the cache entry's output stream.
+     *
+     * @param url the URL for which the cache entry should be added
+     * @param cacheResult the cache entry to add
+     * @deprecated Access to the HTTP cache will be removed in a future release.
+     */
+    @Deprecated
+    public static void saveCacheFile(String url, CacheResult cacheResult) {
+        saveCacheFile(url, 0, cacheResult);
+    }
+
+    static void saveCacheFile(String url, long postIdentifier,
+            CacheResult cacheRet) {
+        try {
+            cacheRet.outStream.close();
+        } catch (IOException e) {
+            return;
+        }
+
+        // This method is exposed in the public API but the API provides no
+        // way to obtain a new CacheResult object with a non-null output
+        // stream ...
+        // - CacheResult objects returned by getCacheFile() have a null
+        //   output stream.
+        // - new CacheResult objects have a null output stream and no
+        //   setter is provided.
+        // Since this method throws a null pointer exception in this case,
+        // it is effectively useless from the point of view of the public
+        // API.
+        //
+        // With the Chromium HTTP stack we continue to throw the same
+        // exception for 'backwards compatibility' with the Android HTTP
+        // stack.
+        //
+        // This method is not used from within this package, and for public API
+        // use, we should already have thrown an exception above.
+        assert false;
+    }
+}
diff --git a/core/java/android/webkit/PluginData.java b/core/java/android/webkit/PluginData.java
new file mode 100644
index 0000000..88fc9b7
--- /dev/null
+++ b/core/java/android/webkit/PluginData.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * This class encapsulates the content generated by a plugin.  The
+ * data itself is meant to be loaded into webkit via the
+ * PluginContentLoader class, which needs to be able to construct an
+ * HTTP response. For this, it needs a stream with the response body,
+ * the length of the body, the response headers, and the response
+ * status code. The PluginData class is the container for all these
+ * parts.
+ *
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
+public final class PluginData {
+    /**
+     * The content stream.
+     */
+    private InputStream mStream;
+    /**
+     * The content length.
+     */
+    private long mContentLength;
+    /**
+     * The associated HTTP response headers stored as a map of
+     * lowercase header name to [ unmodified header name, header value].
+     * TODO: This design was always a hack. Remove (involves updating
+     * the Gears C++ side).
+     */
+    private Map<String, String[]> mHeaders;
+
+    /**
+     * The associated HTTP response code.
+     */
+    private int mStatusCode;
+
+    /**
+     * Creates a PluginData instance.
+     *
+     * @param stream The stream that supplies content for the plugin.
+     * @param length The length of the plugin content.
+     * @param headers The response headers. Map of
+     * lowercase header name to [ unmodified header name, header value]
+     * @param length The HTTP response status code.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public PluginData(
+            InputStream stream,
+            long length,
+            Map<String, String[]> headers,
+            int code) {
+        mStream = stream;
+        mContentLength = length;
+        mHeaders = headers;
+        mStatusCode = code;
+    }
+
+    /**
+     * Returns the input stream that contains the plugin content.
+     *
+     * @return An InputStream instance with the plugin content.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public InputStream getInputStream() {
+        return mStream;
+    }
+
+    /**
+     * Returns the length of the plugin content.
+     *
+     * @return the length of the plugin content.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public long getContentLength() {
+        return mContentLength;
+    }
+
+    /**
+     * Returns the HTTP response headers associated with the plugin
+     * content.
+     *
+     * @return A Map<String, String[]> containing all headers. The
+     * mapping is 'lowercase header name' to ['unmodified header
+     * name', header value].
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public Map<String, String[]> getHeaders() {
+        return mHeaders;
+    }
+
+    /**
+     * Returns the HTTP status code for the response.
+     *
+     * @return The HTTP statue code, e.g 200.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public int getStatusCode() {
+        return mStatusCode;
+    }
+}
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
new file mode 100644
index 0000000..59fc0cb
--- /dev/null
+++ b/core/java/android/webkit/UrlInterceptHandler.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 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.webkit;
+
+import android.webkit.CacheManager.CacheResult;
+import android.webkit.PluginData;
+import java.util.Map;
+
+/**
+ * @hide
+ * @deprecated This interface was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
+public interface UrlInterceptHandler {
+
+    /**
+     * Given an URL, returns the CacheResult which contains the
+     * surrogate response for the request, or null if the handler is
+     * not interested.
+     *
+     * @param url URL string.
+     * @param headers The headers associated with the request. May be null.
+     * @return The CacheResult containing the surrogate response.
+     *
+     * @hide
+     * @deprecated Do not use, this interface is deprecated.
+     */
+    @Deprecated
+    public CacheResult service(String url, Map<String, String> headers);
+
+    /**
+     * Given an URL, returns the PluginData which contains the
+     * surrogate response for the request, or null if the handler is
+     * not interested.
+     *
+     * @param url URL string.
+     * @param headers The headers associated with the request. May be null.
+     * @return The PluginData containing the surrogate response.
+     *
+     * @hide
+     * @deprecated Do not use, this interface is deprecated.
+     */
+    @Deprecated
+    public PluginData getPluginData(String url, Map<String, String> headers);
+}
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
new file mode 100644
index 0000000..bdf6747
--- /dev/null
+++ b/core/java/android/webkit/UrlInterceptRegistry.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2008 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.webkit;
+
+import android.webkit.CacheManager.CacheResult;
+import android.webkit.PluginData;
+import android.webkit.UrlInterceptHandler;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * @hide
+ * @deprecated This class was intended to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
+public final class UrlInterceptRegistry {
+
+    private final static String LOGTAG = "intercept";
+
+    private static boolean mDisabled = false;
+
+    private static LinkedList mHandlerList;
+
+    private static synchronized LinkedList getHandlers() {
+        if(mHandlerList == null)
+            mHandlerList = new LinkedList<UrlInterceptHandler>();
+        return mHandlerList;
+    }
+
+    /**
+     * set the flag to control whether url intercept is enabled or disabled
+     * 
+     * @param disabled true to disable the cache
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public static synchronized void setUrlInterceptDisabled(boolean disabled) {
+        mDisabled = disabled;
+    }
+
+    /**
+     * get the state of the url intercept, enabled or disabled
+     * 
+     * @return return if it is disabled
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public static synchronized boolean urlInterceptDisabled() {
+        return mDisabled;
+    }
+
+    /**
+     * Register a new UrlInterceptHandler. This handler will be called
+     * before any that were previously registered.
+     *
+     * @param handler The new UrlInterceptHandler object
+     * @return true if the handler was not previously registered.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public static synchronized boolean registerHandler(
+            UrlInterceptHandler handler) {
+        if (!getHandlers().contains(handler)) {
+            getHandlers().addFirst(handler);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Unregister a previously registered UrlInterceptHandler.
+     *
+     * @param handler A previously registered UrlInterceptHandler.
+     * @return true if the handler was found and removed from the list.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public static synchronized boolean unregisterHandler(
+            UrlInterceptHandler handler) {
+        return getHandlers().remove(handler);
+    }
+
+    /**
+     * Given an url, returns the CacheResult of the first
+     * UrlInterceptHandler interested, or null if none are.
+     *
+     * @return A CacheResult containing surrogate content.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public static synchronized CacheResult getSurrogate(
+            String url, Map<String, String> headers) {
+        if (urlInterceptDisabled()) {
+            return null;
+        }
+        Iterator iter = getHandlers().listIterator();
+        while (iter.hasNext()) {
+            UrlInterceptHandler handler = (UrlInterceptHandler) iter.next();
+            CacheResult result = handler.service(url, headers);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Given an url, returns the PluginData of the first
+     * UrlInterceptHandler interested, or null if none are or if
+     * intercepts are disabled.
+     *
+     * @return A PluginData instance containing surrogate content.
+     *
+     * @hide
+     * @deprecated This class was intended to be used by Gears. Since Gears was
+     * deprecated, so is this class.
+     */
+    @Deprecated
+    public static synchronized PluginData getPluginData(
+            String url, Map<String, String> headers) {
+        if (urlInterceptDisabled()) {
+            return null;
+        }
+        Iterator iter = getHandlers().listIterator();
+        while (iter.hasNext()) {
+            UrlInterceptHandler handler = (UrlInterceptHandler) iter.next();
+            PluginData data = handler.getPluginData(url, headers);
+            if (data != null) {
+                return data;
+            }
+        }
+        return null;
+    }
+}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 4614c53..01ac8fd 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.IntProperty;
 import android.util.MathUtils;
@@ -176,6 +177,9 @@
      */
     private int mState;
 
+    /** Whether the preview image is visible. */
+    private boolean mShowingPreview;
+
     private BaseAdapter mListAdapter;
     private SectionIndexer mSectionIndexer;
 
@@ -769,6 +773,8 @@
         mDecorAnimation = new AnimatorSet();
         mDecorAnimation.playTogether(fadeOut, slideOut);
         mDecorAnimation.start();
+
+        mShowingPreview = false;
     }
 
     /**
@@ -790,6 +796,8 @@
         mDecorAnimation = new AnimatorSet();
         mDecorAnimation.playTogether(fadeIn, fadeOut, slideIn);
         mDecorAnimation.start();
+
+        mShowingPreview = false;
     }
 
     /**
@@ -809,6 +817,8 @@
         mDecorAnimation = new AnimatorSet();
         mDecorAnimation.playTogether(fadeIn, slideIn);
         mDecorAnimation.start();
+
+        mShowingPreview = true;
     }
 
     private void postAutoHide() {
@@ -982,9 +992,10 @@
         if (mCurrentSection != sectionIndex) {
             mCurrentSection = sectionIndex;
 
-            if (transitionPreviewLayout(sectionIndex)) {
+            final boolean hasPreview = transitionPreviewLayout(sectionIndex);
+            if (!mShowingPreview && hasPreview) {
                 transitionToDragging();
-            } else {
+            } else if (mShowingPreview && !hasPreview) {
                 transitionToVisible();
             }
         }
@@ -1072,7 +1083,7 @@
 
         mPreviewAnimation.start();
 
-        return (text != null && text.length() > 0);
+        return !TextUtils.isEmpty(text);
     }
 
     /**
@@ -1184,7 +1195,19 @@
                     / positionsInSection;
         }
 
-        return (section + posWithinSection) / sectionCount;
+        float result = (section + posWithinSection) / sectionCount;
+
+        // Fake out the scroll bar for the last item. Since the section indexer
+        // won't ever actually move the list in this end space, make scrolling
+        // across the last item account for whatever space is remaining.
+        if (firstVisibleItem > 0 && firstVisibleItem + visibleItemCount == totalItemCount) {
+            final View lastChild = mList.getChildAt(visibleItemCount - 1);
+            final float lastItemVisible = (float) (mList.getHeight() - mList.getPaddingBottom()
+                    - lastChild.getTop()) / lastChild.getHeight();
+            result += (1 - result) * lastItemVisible;
+        }
+
+        return result;
     }
 
     /**
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 368f6ad..fd2f754 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -92,7 +92,9 @@
                 com.android.internal.R.styleable.Theme_quickContactBadgeOverlay);
         styledAttributes.recycle();
 
-        mQueryHandler = new QueryHandler(mContext.getContentResolver());
+        if (!isInEditMode()) {
+            mQueryHandler = new QueryHandler(mContext.getContentResolver());
+        }
         setOnClickListener(this);
     }
 
@@ -199,7 +201,7 @@
     public void assignContactFromEmail(String emailAddress, boolean lazyLookup, Bundle extras) {
         mContactEmail = emailAddress;
         mExtras = extras;
-        if (!lazyLookup) {
+        if (!lazyLookup && mQueryHandler != null) {
             mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, null,
                     Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
                     EMAIL_LOOKUP_PROJECTION, null, null, null);
@@ -239,7 +241,7 @@
     public void assignContactFromPhone(String phoneNumber, boolean lazyLookup, Bundle extras) {
         mContactPhone = phoneNumber;
         mExtras = extras;
-        if (!lazyLookup) {
+        if (!lazyLookup && mQueryHandler != null) {
             mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, null,
                     Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
                     PHONE_LOOKUP_PROJECTION, null, null, null);
@@ -262,12 +264,12 @@
         if (mContactUri != null) {
             QuickContact.showQuickContact(getContext(), QuickContactBadge.this, mContactUri,
                     QuickContact.MODE_LARGE, mExcludeMimes);
-        } else if (mContactEmail != null) {
+        } else if (mContactEmail != null && mQueryHandler != null) {
             extras.putString(EXTRA_URI_CONTENT, mContactEmail);
             mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, extras,
                     Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
                     EMAIL_LOOKUP_PROJECTION, null, null, null);
-        } else if (mContactPhone != null) {
+        } else if (mContactPhone != null && mQueryHandler != null) {
             extras.putString(EXTRA_URI_CONTENT, mContactPhone);
             mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, extras,
                     Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 222e446..20b8c95 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -135,10 +135,10 @@
     };
 
     static final String[] STATE_NAMES = new String[] {
-            "Persistent", "Top       ", "Imp Fg    ", "Imp Bg    ",
-            "Backup    ", "Heavy Wght", "Service   ", "Service Rs",
-            "Receiver  ", "Home      ",
-            "Last Act  ", "Cch Act   ", "Cch CliAct", "Cch Empty "
+            "Persist", "Top    ", "ImpFg  ", "ImpBg  ",
+            "Backup ", "HeavyWt", "Service", "ServRst",
+            "Receivr", "Home   ",
+            "LastAct", "CchAct ", "CchCAct", "CchEmty"
     };
 
     public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
@@ -314,16 +314,16 @@
     private static void printScreenLabel(PrintWriter pw, int offset) {
         switch (offset) {
             case ADJ_NOTHING:
-                pw.print("             ");
+                pw.print("     ");
                 break;
             case ADJ_SCREEN_OFF:
-                pw.print("Screen Off / ");
+                pw.print("SOff/");
                 break;
             case ADJ_SCREEN_ON:
-                pw.print("Screen On  / ");
+                pw.print("SOn /");
                 break;
             default:
-                pw.print("?????????? / ");
+                pw.print("????/");
                 break;
         }
     }
@@ -344,25 +344,31 @@
         }
     }
 
-    private static void printMemLabel(PrintWriter pw, int offset) {
+    private static void printMemLabel(PrintWriter pw, int offset, char sep) {
         switch (offset) {
             case ADJ_NOTHING:
-                pw.print("       ");
+                pw.print("    ");
+                if (sep != 0) pw.print(' ');
                 break;
             case ADJ_MEM_FACTOR_NORMAL:
-                pw.print("Norm / ");
+                pw.print("Norm");
+                if (sep != 0) pw.print(sep);
                 break;
             case ADJ_MEM_FACTOR_MODERATE:
-                pw.print("Mod  / ");
+                pw.print("Mod ");
+                if (sep != 0) pw.print(sep);
                 break;
             case ADJ_MEM_FACTOR_LOW:
-                pw.print("Low  / ");
+                pw.print("Low ");
+                if (sep != 0) pw.print(sep);
                 break;
             case ADJ_MEM_FACTOR_CRITICAL:
-                pw.print("Crit / ");
+                pw.print("Crit");
+                if (sep != 0) pw.print(sep);
                 break;
             default:
-                pw.print("???? / ");
+                pw.print("????");
+                if (sep != 0) pw.print(sep);
                 break;
         }
     }
@@ -399,8 +405,9 @@
                         printScreenLabel(pw, printedScreen != iscreen
                                 ? iscreen : STATE_NOTHING);
                         printedScreen = iscreen;
-                        printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                        printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
                         printedMem = imem;
+                        pw.print(": ");
                         TimeUtils.formatDuration(time, pw); pw.println(running);
                     }
                     totalTime += time;
@@ -409,8 +416,7 @@
         }
         if (totalTime != 0 && pw != null) {
             pw.print(prefix);
-            printScreenLabel(pw, STATE_NOTHING);
-            pw.print("TOTAL: ");
+            pw.print("    TOTAL: ");
             TimeUtils.formatDuration(totalTime, pw);
             pw.println();
         }
@@ -569,7 +575,7 @@
                             printedScreen = iscreen;
                         }
                         if (memStates.length > 1) {
-                            printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                            printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
                             printedMem = imem;
                         }
                         pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
@@ -585,9 +591,9 @@
                 printScreenLabel(pw, STATE_NOTHING);
             }
             if (memStates.length > 1) {
-                printMemLabel(pw, STATE_NOTHING);
+                printMemLabel(pw, STATE_NOTHING, '/');
             }
-            pw.print("TOTAL     : ");
+            pw.print("TOTAL  : ");
             TimeUtils.formatDuration(totalTime, pw);
             pw.println();
         }
@@ -621,7 +627,7 @@
                             printedScreen = iscreen;
                         }
                         if (memStates.length > 1) {
-                            printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                            printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, '/');
                             printedMem = imem;
                         }
                         pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
@@ -798,7 +804,7 @@
                     new int[] {STATE_SERVICE_RESTARTING}, now, totalTime, true);
             dumpProcessSummaryDetails(pw, proc, prefix, "      Receiver: ", screenStates, memStates,
                     new int[] {STATE_RECEIVER}, now, totalTime, true);
-            dumpProcessSummaryDetails(pw, proc, prefix, "          Home: ", screenStates, memStates,
+            dumpProcessSummaryDetails(pw, proc, prefix, "        (Home): ", screenStates, memStates,
                     new int[] {STATE_HOME}, now, totalTime, true);
             dumpProcessSummaryDetails(pw, proc, prefix, "    (Last Act): ", screenStates, memStates,
                     new int[] {STATE_LAST_ACTIVITY}, now, totalTime, true);
@@ -1733,13 +1739,17 @@
                         pw.print(" pkg="); pw.println(proc.mCommonProcess.mPackage);
             }
         }
-        pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive);
+        if (proc.mActive) {
+            pw.print(prefix); pw.print("mActive="); pw.println(proc.mActive);
+        }
         if (proc.mDead) {
             pw.print(prefix); pw.print("mDead="); pw.println(proc.mDead);
         }
-        pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices);
-                pw.print(" mNumStartedServices=");
-                pw.println(proc.mNumStartedServices);
+        if (proc.mNumActiveServices != 0 || proc.mNumStartedServices != 0) {
+            pw.print(prefix); pw.print("mNumActiveServices="); pw.print(proc.mNumActiveServices);
+                    pw.print(" mNumStartedServices=");
+                    pw.println(proc.mNumStartedServices);
+        }
     }
 
     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
@@ -1920,8 +1930,9 @@
                         printScreenLabel(pw, printedScreen != iscreen
                                 ? iscreen : STATE_NOTHING);
                         printedScreen = iscreen;
-                        printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                        printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
                         printedMem = imem;
+                        pw.print(": ");
                         TimeUtils.formatDuration(time, pw); pw.println(running);
                     }
                     totalTime += time;
@@ -1930,8 +1941,7 @@
         }
         if (totalTime != 0 && pw != null) {
             pw.print(prefix);
-            printScreenLabel(pw, STATE_NOTHING);
-            pw.print("TOTAL: ");
+            pw.print("    TOTAL: ");
             TimeUtils.formatDuration(totalTime, pw);
             pw.println();
         }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index cd853b6..591267e 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -181,11 +181,12 @@
             } else {
                 mAlwaysUseOption = false;
             }
-        }
-        final int initialHighlight = mAdapter.getInitialHighlight();
-        if (initialHighlight >= 0) {
-            mListView.setItemChecked(initialHighlight, true);
-            onItemClick(null, null, initialHighlight, 0); // Other entries are not used
+            // Set the initial highlight if there was a preferred or last used choice
+            final int initialHighlight = mAdapter.getInitialHighlight();
+            if (initialHighlight >= 0) {
+                mListView.setItemChecked(initialHighlight, true);
+                onItemClick(null, null, initialHighlight, 0); // Other entries are not used
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/inputmethod/InputMethodRoot.java b/core/java/com/android/internal/inputmethod/InputMethodRoot.java
deleted file mode 100644
index eddea99..0000000
--- a/core/java/com/android/internal/inputmethod/InputMethodRoot.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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 com.android.internal.inputmethod;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-
-public class InputMethodRoot extends LinearLayout {
-
-    private View mNavigationGuard;
-
-    public InputMethodRoot(Context context) {
-        this(context, null);
-    }
-
-    public InputMethodRoot(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public InputMethodRoot(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        requestFitSystemWindows();
-    }
-
-    @Override
-    protected boolean fitSystemWindows(Rect insets) {
-        if (mNavigationGuard == null) {
-            mNavigationGuard = findViewById(com.android.internal.R.id.navigationGuard);
-        }
-        if (mNavigationGuard == null) {
-            return super.fitSystemWindows(insets);
-        }
-        ViewGroup.LayoutParams lp = mNavigationGuard.getLayoutParams();
-        lp.height = insets.bottom;
-        mNavigationGuard.setLayoutParams(lp);
-        return true;
-    }
-}
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 45a38be..63ff5a0 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -43,4 +43,5 @@
     oneway void showAssistant();
     oneway void dispatch(in MotionEvent event);
     oneway void launchCamera();
+    oneway void onBootCompleted();
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index e09fcff..5983120 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -60,7 +60,6 @@
 	android_text_AndroidCharacter.cpp \
 	android_text_AndroidBidi.cpp \
 	android_os_Debug.cpp \
-	android_os_FileUtils.cpp \
 	android_os_MemoryFile.cpp \
 	android_os_MessageQueue.cpp \
 	android_os_Parcel.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 8518101..09577da 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -142,7 +142,6 @@
 extern int register_android_os_SystemClock(JNIEnv* env);
 extern int register_android_os_Trace(JNIEnv* env);
 extern int register_android_os_FileObserver(JNIEnv *env);
-extern int register_android_os_FileUtils(JNIEnv *env);
 extern int register_android_os_UEventObserver(JNIEnv* env);
 extern int register_android_os_MemoryFile(JNIEnv* env);
 extern int register_android_net_LocalSocketImpl(JNIEnv* env);
@@ -1169,7 +1168,6 @@
     REG_JNI(register_android_database_SQLiteDebug),
     REG_JNI(register_android_os_Debug),
     REG_JNI(register_android_os_FileObserver),
-    REG_JNI(register_android_os_FileUtils),
     REG_JNI(register_android_os_MessageQueue),
     REG_JNI(register_android_os_SELinux),
     REG_JNI(register_android_os_Trace),
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index a0c50fa..92d253f 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -721,7 +721,8 @@
         
         hb_buffer_set_direction(mBuffer, isRTL ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
         hb_buffer_set_script(mBuffer, run.script);
-        // Should set language here (for bug 7004056)
+        SkString langString = paint->getPaintOptionsAndroid().getLanguage().getTag();
+        hb_buffer_set_language(mBuffer, hb_language_from_string(langString.c_str(), -1));
         hb_buffer_add_utf16(mBuffer, contextChars, contextCount, start + run.pos, run.length);
 
         // Initialize Harfbuzz Shaper and get the base glyph count for offsetting the glyphIDs
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
deleted file mode 100644
index d1245da..0000000
--- a/core/jni/android_os_FileUtils.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/* //device/libs/android_runtime/android_util_Process.cpp
-**
-** Copyright 2006, 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.
-*/
-
-#define LOG_TAG "FileUtils"
-
-#include <utils/Log.h>
-
-#include <android_runtime/AndroidRuntime.h>
-
-#include "JNIHelp.h"
-
-#include <sys/errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <linux/msdos_fs.h>
-
-namespace android {
-
-jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
-{
-    if (path == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return -1;
-    }
-    const char *pathStr = env->GetStringUTFChars(path, NULL);
-    int result = -1;
-    // only if our system supports this ioctl
-    #ifdef VFAT_IOCTL_GET_VOLUME_ID
-    int fd = open(pathStr, O_RDONLY);
-    if (fd >= 0) {
-        result = ioctl(fd, VFAT_IOCTL_GET_VOLUME_ID);
-        close(fd);
-    }
-    #endif
-
-    env->ReleaseStringUTFChars(path, pathStr);
-    return result;
-}
-
-static const JNINativeMethod methods[] = {
-    {"getFatVolumeId",  "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
-};
-
-static const char* const kFileUtilsPathName = "android/os/FileUtils";
-
-int register_android_os_FileUtils(JNIEnv* env)
-{
-    return AndroidRuntime::registerNativeMethods(
-        env, kFileUtilsPathName,
-        methods, NELEM(methods));
-}
-
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index eba6231..bd52f49 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1958,8 +1958,7 @@
 
     <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
          or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
-         the system can bind to it.
-         @hide -->
+         the system can bind to it. -->
     <permission android:name="android.permission.BIND_NFC_SERVICE"
         android:label="@string/permlab_bindNfcService"
         android:description="@string/permdesc_bindNfcService"
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index 3b64f47..28a1cba 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index 3b64f47..28a1cba 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index 6a2a92c..72b0d42 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index 6a2a92c..72b0d42 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index b9266a6..eff3cc4 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index b9266a6..eff3cc4 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index 42fc83c..986f797 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 87933fa..3ce61b3 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 87933fa..3ce61b3 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index d424a0e..82e54fd 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index d424a0e..82e54fd 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index 0763868..c389871 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index 0763868..c389871 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index accc761..211be67 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
index d591bf8..41230fe9 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
index d591bf8..41230fe9 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
index b410d23..9fa8682 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
index b410d23..9fa8682 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
index aed57c6..73488f3 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
index aed57c6..73488f3 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
index 38f8c01..28edccd 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/layout/input_method.xml b/core/res/res/layout/input_method.xml
index e50da00..79f1ce8 100644
--- a/core/res/res/layout/input_method.xml
+++ b/core/res/res/layout/input_method.xml
@@ -18,12 +18,11 @@
 */
 -->
 
-<com.android.internal.inputmethod.InputMethodRoot xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:gravity="start|bottom"
     >
 
     <LinearLayout
@@ -54,8 +53,4 @@
         android:visibility="gone">
     </FrameLayout>
 
-    <View android:id="@+id/navigationGuard"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:background="@+color/input_method_navigation_guard"/>
-</com.android.internal.inputmethod.InputMethodRoot>
+</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 1a9acd3..ae310bf 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"Probeer weer oor <xliff:g id="COUNT">%d</xliff:g> sekondes"</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Probeer later weer"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Sleep van bo af na onder om volskerm te verlaat."</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Swiep van bo af na onder om volskerm te verlaat."</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e64b6f5..0ae0feb 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -175,7 +175,7 @@
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"ኤስ ኤም ኤስህን፣ ኢሜይልህን እና ሌላ መልዕክቶችህን አንብብና ፃፍ።"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"የግል መረጃዎ"</string>
     <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"በእውቂያ ካርድህ ላይ ወደተከማቸ የአንተ መረጃ ቀጥተኛ መዳረሻ።"</string>
-    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ማህበራዊ መረጃህ"</string>
+    <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ማህበራዊ መረጃዎ"</string>
     <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"ወደ የእውቂያዎችህና የማህበራዊ ግንኙነቶችህ መረጃ ቀጥተኛ መዳረሻ።"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"ስፍራዎ"</string>
     <string name="permgroupdesc_location" msgid="5704679763124170100">"ያለህበትን አካባቢ ተቆጣጠር።"</string>
@@ -450,9 +450,9 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ስለ ገቢ እና ወጪ ጥሪዎችን ውሂብ ጨምሮ፣ የጡባዊተኮህን ምዝግብ ማስታወሻ ለመቀየር ለመተግበሪያው ይፈቅዳል። ይሄንን ተንኮል አዘል መተግበሪያዎች የስልክህን ምዝግብ ማስታወሻ ለመሰረዝ ወይም ለመለወጥ ሊጠቀሙበት ይችላሉ።"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"ስለ ገቢ እና ወጪ ጥሪዎችን ውሂብ ጨምሮ፣ የስልክህን ምዝግብ ማስታወሻ ለመቀየር ለመተግበሪያው ይፈቅዳል። ይሄንን ተንኮል አዘል መተግበሪያዎች የስልክህን ምዝግብ ማስታወሻ ለመሰረዝ ወይም ለመለወጥ ሊጠቀሙበት ይችላሉ።"</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"የራስህን የእውቂያ ካርድ አንብብ"</string>
-    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"መተግበሪያው ልክ እንደ ስምህ እና የእውቂያ መረጃህ ያሉ በመሳሪያህ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲያነብ ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቅህ እና የመገለጫ መረጃህን ለሌሎች ሊልክ ይችላል።"</string>
+    <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"መተግበሪያው ልክ እንደ ስምዎ እና የእውቂያ መረጃዎ ያሉ በመሳሪያዎ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲያነብ ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቁዎ እና የመገለጫ መረጃዎን ለሌሎች ሊልክ ይችላል።"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"የራስህን የዕውቂያ ካርድ አስተካክል"</string>
-    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"መተግበሪያው ልክ እንደ ስምህ እና የእውቂያ መረጃህ ያሉ በመሳሪያህ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲቀይር ወይም እንዲያክልባቸው ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቅህ እና የመገለጫ መረጃህን ለሌሎች ሊልክ ይችላል።"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"መተግበሪያው ልክ እንደ ስምዎ እና የእውቂያ መረጃዎ ያሉ በመሳሪያዎ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲቀይር ወይም እንዲያክልባቸው ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቅዎ እና የመገለጫ መረጃዎን ለሌሎች ሊልክ ይችላል።"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"የአንተን ማህበራዊ የውይይት ክፍሎች አንብብ"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"መተግበሪያው የአንተንና የጓኞችህን ማህበራዊ ዝማኔዎችን እንዲደርስባቸው እና እንዲያመሳስላቸው ይፈቅድለታል። መረጃ ስታጋራ ተጠንቀቅ -- ይህ መተግበሪያው ሚስጥራዊነትን ከግምት ሳያስገባ በማህበራዊ አውታረ መረቦች በአንተ እና በጓደኞችህ መካከል የሚደረጉ ግንኙነቶችን እንዲያነብ ይፈቅድለታል። ማስታወሻ፦ ይህ ፈቃድ ለሁሉም ማህበራዊ አውታር መረቦች ላይ ላይፈጸም ይችላል።"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ወደ የአንተ  ማህበራዊ የውይይት ክፍሎች ጻፍ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 2d91e28..98ae2c3 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -43,7 +43,7 @@
     <string name="serviceErased" msgid="1288584695297200972">"لم يتم المسح بنجاح."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"كلمة مرور غير صحيحة."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"اكتمل MMI."</string>
-    <string name="badPin" msgid="9015277645546710014">"رقم التعريف الشخصي القديم الذي كتبته غير صحيح."</string>
+    <string name="badPin" msgid="9015277645546710014">"رمز PIN القديم الذي كتبته غير صحيح."</string>
     <string name="badPuk" msgid="5487257647081132201">"رمز PUK الذي كتبته غير صحيح."</string>
     <string name="mismatchPin" msgid="609379054496863419">"أرقام التعريف الشخصية التي كتبتها غير مطابقة."</string>
     <string name="invalidPin" msgid="3850018445187475377">"اكتب رقم تعريف شخصيًا مكونًا من 4 إلى ثمانية أعداد."</string>
@@ -54,11 +54,11 @@
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"معرف المتصل الوارد"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"معرف المتصل الصادر"</string>
-    <string name="CfMmi" msgid="5123218989141573515">"إعادة توجيه الاتصال"</string>
+    <string name="CfMmi" msgid="5123218989141573515">"اعادة توجيه المكالمة"</string>
     <string name="CwMmi" msgid="9129678056795016867">"انتظار المكالمة"</string>
     <string name="BaMmi" msgid="455193067926770581">"حظر الاتصال"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"تغيير كلمة المرور"</string>
-    <string name="PinMmi" msgid="3113117780361190304">"تغيير رقم التعريف الشخصي"</string>
+    <string name="PinMmi" msgid="3113117780361190304">"تغيير رمز PIN"</string>
     <string name="CnipMmi" msgid="3110534680557857162">"رقم الاتصال موجود"</string>
     <string name="CnirMmi" msgid="3062102121430548731">"رقم الاتصال مقيّد"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"اتصال ثلاثي"</string>
@@ -259,7 +259,7 @@
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"تلقي بث الطوارئ"</string>
     <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"للسماح للتطبيق بتلقي رسائل بث الطوارئ ومعالجتها. لا يتوفر هذا الإذن سوى لتطبيقات النظام."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"قراءة رسائل بث الخلية"</string>
-    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم تنبيهات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
+    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
     <string name="permlab_sendSms" msgid="5600830612147671529">"إرسال رسائل قصيرة SMS"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"للسماح للتطبيق بإرسال رسائل قصيرة SMS. وقد يؤدي هذا إلى تحمل رسوم غير متوقعة. وقد تكلفك التطبيقات الضارة أموالاً من خلال إرسال رسائل بدون موافقة منك."</string>
     <string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"إرسال أحداث يتم الرد عليها عبر رسالة"</string>
@@ -809,14 +809,14 @@
     <string name="sipAddressTypeHome" msgid="6093598181069359295">"المنزل"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"العمل"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"غير ذلك"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"اكتب رمز رقم التعريف الشخصي"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"اكتب رمز PUK ورمز رقم التعريف الشخصي الجديد"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"اكتب رمز رمز PIN"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"اكتب رمز PUK ورمز رمز PIN الجديد"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"رمز PUK"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"رمز رقم التعريف الشخصي الجديد"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"رمز رمز PIN الجديد"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"المس لكتابة كلمة المرور"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"اكتب كلمة المرور لإلغاء التأمين"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"اكتب رقم التعريف الشخصي لإلغاء التأمين"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"رقم التعريف الشخصي غير صحيح."</string>
+    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"اكتب رمز PIN لإلغاء التأمين"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"رمز PIN غير صحيح."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"لإلغاء التأمين، اضغط على \"القائمة\" ثم على 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"رقم الطوارئ"</string>
     <string name="lockscreen_carrier_default" msgid="8963839242565653192">"لا تتوفر خدمة"</string>
@@ -854,7 +854,7 @@
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"لقد رسمت نقش إلغاء التأمين بطريقة غير صحيحة <xliff:g id="NUMBER_0">%d</xliff:g> مرة.\n\nالرجاء إعادة المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"لقد كتبت كلمة المرور <xliff:g id="NUMBER_0">%d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"لقد كتبت رقم التعريف الشخصي <xliff:g id="NUMBER_0">%d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"لقد كتبت رمز PIN <xliff:g id="NUMBER_0">%d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات تسجيل الدخول إلى Google.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام معلومات تسجيل الدخول إلى Google.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"لقد حاولت إلغاء تأمين الجهاز اللوحي <xliff:g id="NUMBER_0">%d</xliff:g> من المرات. بعد <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة، ستتم إعادة تعيين الجهاز اللوحي إلى الإعدادات الافتراضية للمصنع وسيتم فقد جميع بيانات المستخدم."</string>
@@ -896,7 +896,7 @@
     <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"إلغاء القفل باستخدام التمرير."</string>
     <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string>
     <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"تأمين الجهاز بالوجه."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رقم التعريف الشخصي."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رمز PIN."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"إلغاء القفل باستخدام كلمة المرور."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"منطقة النقش."</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"منطقة التمرير."</string>
@@ -1198,8 +1198,8 @@
     <string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"دعوة للاتصال"</string>
     <string name="wifi_p2p_from_message" msgid="570389174731951769">"من:"</string>
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"إلى:"</string>
-    <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"اكتب رقم التعريف الشخصي المطلوب:"</string>
-    <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"رقم التعريف الشخصي:"</string>
+    <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"اكتب رمز PIN المطلوب:"</string>
+    <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"رمز PIN:"</string>
     <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"سيتم قطع اتصال الجهاز اللوحي مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"سيتم قطع اتصال الهاتف مؤقتًا بشبكة Wi-Fi في الوقت الذي يكون فيه متصلاً بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"إدراج حرف"</string>
@@ -1505,18 +1505,18 @@
     <string name="kg_wrong_pin" msgid="1131306510833563801">"رقم تعريف شخصي خاطئ"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"حاول مرة أخرى خلال <xliff:g id="NUMBER">%1$d</xliff:g> ثانية."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"ارسم نقشك"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"أدخل رقم التعريف الشخصي لبطاقة SIM"</string>
-    <string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رقم التعريف الشخصي"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"أدخل رمز PIN لبطاقة SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رمز PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"أدخل كلمة المرور"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"بطاقة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رقم التعريف الشخصي المراد"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رقم التعريف الشخصي المراد"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رمز PIN المراد"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رمز PIN المراد"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
-    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رقم التعريف الشخصي غير صحيح."</string>
-    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رقم التعريف الشخصي المكون من 4 إلى 8 أرقام."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رمز PIN غير صحيح."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رمز PIN المكون من 4 إلى 8 أرقام."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"يجب أن يتضمن رمز PUK‏ 8 أرقام أو أكثر."</string>
     <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل بطاقة SIM نهائيًا."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رقم التعريف الشخصي"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رمز PIN"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"لإلغاء التأمين، سجّل الدخول بحسابك في Google."</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"اسم المستخدم (البريد إلكتروني)"</string>
@@ -1525,7 +1525,7 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"اسم مستخدم غير صحيح أو كلمة مرور غير صالحة."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"هل نسيت اسم المستخدم أو كلمة المرور؟\nانتقل إلى "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"جارٍ فحص الحساب…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"لقد كتبت رقم التعريف الشخصي بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"لقد كتبت رمز PIN بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"لقد كتبت كلمة المرور بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"لقد رسمت نقش إلغاء التأمين بطريقة غير صحيحة <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"لقد حاولت إلغاء تأمين الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الجهاز اللوحي على الإعدادات الافتراضية للمصنع وسيتم فقد جميع بيانات المستخدم."</string>
@@ -1635,15 +1635,15 @@
     <string name="reason_service_unavailable" msgid="7824008732243903268">"خدمة الطباعة ليست ممكّنة"</string>
     <string name="print_service_installed_title" msgid="2246317169444081628">"تم تثبيت خدمة <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="print_service_installed_message" msgid="5897362931070459152">"انقر للتمكين."</string>
-    <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"أدخل رقم التعريف الشخصي للمشرف"</string>
-    <string name="restr_pin_enter_pin" msgid="3395953421368476103">"إدخال رقم التعريف الشخصي"</string>
+    <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"أدخل رمز PIN للمشرف"</string>
+    <string name="restr_pin_enter_pin" msgid="3395953421368476103">"إدخال رمز PIN"</string>
     <string name="restr_pin_incorrect" msgid="8571512003955077924">"غير صحيح"</string>
-    <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"رقم التعريف الشخصي الحالي"</string>
-    <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"رقم التعريف الشخصي الجديد"</string>
-    <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"تأكيد رقم التعريف الشخصي الجديد"</string>
+    <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"رمز PIN الحالي"</string>
+    <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"رمز PIN الجديد"</string>
+    <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"تأكيد رمز PIN الجديد"</string>
     <string name="restr_pin_create_pin" msgid="8017600000263450337">"إنشاء رقم تعريف شخصي لتعديل القيود"</string>
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"أرقام التعريف الشخصية لا تتطابق، أعد المحاولة."</string>
-    <string name="restr_pin_error_too_short" msgid="8173982756265777792">"رقم التعريف الشخصي أقصر مما يلزم، يجب ألا يقل عن 4 أرقام. "</string>
+    <string name="restr_pin_error_too_short" msgid="8173982756265777792">"رمز PIN أقصر مما يلزم، يجب ألا يقل عن 4 أرقام. "</string>
   <plurals name="restr_pin_countdown">
     <item quantity="one" msgid="311050995198548675">"أعد المحاولة خلال ثانية واحدة."</item>
     <item quantity="other" msgid="4730868920742952817">"أعد المحاولة خلال <xliff:g id="COUNT">%d</xliff:g> ثانية"</item>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 8b46e84..6d18688 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1485,7 +1485,7 @@
     <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla sense fil"</string>
     <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fet"</string>
     <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortida de contingut multimèdia"</string>
-    <string name="media_route_status_scanning" msgid="7279908761758293783">"S\'està explorant..."</string>
+    <string name="media_route_status_scanning" msgid="7279908761758293783">"S\'està cercant…"</string>
     <string name="media_route_status_connecting" msgid="6422571716007825440">"S\'està connectant..."</string>
     <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string>
     <string name="media_route_status_not_available" msgid="6739899962681886401">"No disponible"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0cf5bc5..63ccd05 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -440,7 +440,7 @@
     <string name="permlab_readContacts" msgid="8348481131899886131">"læse dine kontaktpersoner"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Tillader, at appen kan læse data om de kontaktpersoner, der er gemt på din tablet, f.eks. hvor ofte du har ringet til, sendt e-mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Tillader, at appen kan læse data om de kontaktpersoner, der er gemt på din telefon, f.eks. hvor ofte du har ringet til, sendt e-mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
-    <string name="permlab_writeContacts" msgid="5107492086416793544">"ændre dine kontaktpersoner"</string>
+    <string name="permlab_writeContacts" msgid="5107492086416793544">"at ændre dine kontaktpersoner"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Tillader, at appen kan ændre data om de kontaktpersoner, der er gemt på din tablet, f.eks. hvor ofte du har ringet til dem, sendt dem en e-mail eller på anden måde kommunikeret med bestemte kontaktpersoner. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Tillader, at appen kan ændre data om de kontaktpersoner, der er gemt på din telefon, f.eks. hvor ofte du har ringet til dem, sendt en e-mail til dem eller på anden måde kommunikeret med bestemte kontaktpersoner. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"læs opkaldsliste"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 3130cba..623f521 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"Yritä uud. <xliff:g id="COUNT">%d</xliff:g> s kul."</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Yritä myöhemmin uudelleen"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Poistu koko näytön tilasta liu\'uttamalla alas."</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Poistu koko näytön tilasta pyyhkäisemällä alas."</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4ae5938..2870ac9 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"Próbálja újra <xliff:g id="COUNT">%d</xliff:g> másodperc múlva"</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Próbálkozzon később"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"A teljes képernyős nézetből való kilépéshez húzza ujját a tetejétől lefelé."</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"A teljes képernyős nézetből való kilépéshez húzza ujját a képernyő tetejétől lefelé."</string>
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 003b3f9..90f248a 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1114,7 +1114,7 @@
     <string name="loading" msgid="7933681260296021180">"ກຳລັງໂຫລດ..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ເປີດ"</string>
     <string name="capital_off" msgid="6815870386972805832">"ປິດ"</string>
-    <string name="whichApplication" msgid="4533185947064773386">"ເຮັດວຽກໃຫ້ສຳເລັດໂດຍໃຊ້"</string>
+    <string name="whichApplication" msgid="4533185947064773386">"ດຳເນີນການໂດຍໃຊ້"</string>
     <string name="whichHomeApplication" msgid="4616420172727326782">"ເລືອກແອັບຯ Home"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"ໃຊ້ໂດຍຄ່າເລີ່ມຕົນສຳລັບການເຮັດວຽກນີ້."</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"ລຶບລ້າງຄ່າເລີ່ມຕົ້ນ ໃນ ການຕັ້ງຄ່າລະບົບ &gt; ແອັບຯ &gt; ດາວໂຫລດແລ້ວ."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index fe3d78b..349dfd2 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> секундын дараа дахин оролдоно уу"</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Дараа дахин оролдоно уу"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Бүтэн дэлгэцээс гарахын тулд дээрээс нь эхлэн доош шудрана уу."</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Бүтэн дэлгэцээс гарахын тулд дээрээс нь доош шудрана уу."</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a587950..ef45d98 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"Jaribu tena baada ya sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Jaribu tena baadaye"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Telezesha kidole kwa kasi chini kuanzia juu ili uondoke kwenye skrini kamili."</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"Telezesha kidole kwa kasi chini kuanzia juu ili uondoke kwenye skrini zima."</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index e3ca5b9..95aca0c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> 秒後再試一次"</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"稍後再試"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"從頂端往下快速滑動即可退出全螢幕。"</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"由頂端往下快速滑動即可離開全螢幕。"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3ec8d4c..1066d38 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1649,5 +1649,5 @@
     <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> 秒後再試一次"</item>
   </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"稍後再試"</string>
-    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"從頂端往下滑動即可結束全螢幕。"</string>
+    <string name="immersive_mode_confirmation" msgid="7227416894979047467">"從頂端往下滑動即可退出全螢幕模式。"</string>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index aad6252..f96195c 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -53,7 +53,7 @@
     <!-- Minimum size of the fastscroll overlay -->
     <dimen name="fastscroll_overlay_size">104dp</dimen>
     <!-- Text size of the fastscroll overlay -->
-    <dimen name="fastscroll_overlay_text_size">24sp</dimen>
+    <dimen name="fastscroll_overlay_text_size">52sp</dimen>
     <!-- Padding of the fastscroll overlay -->
     <dimen name="fastscroll_overlay_padding">16dp</dimen>
     <!-- Width of the fastscroll thumb -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 15df295..5c0baaa 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -81,4 +81,5 @@
   <item type="id" name="popup_submenu_presenter" />
   <item type="id" name="action_bar_spinner" />
   <item type="id" name="current_scene" />
+  <item type="id" name="scene_layoutid_cache" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e82ad1e..490eab8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -97,6 +97,13 @@
          the SIM card. -->
     <string name="needPuk">Your SIM card is PUK-locked. Type the PUK code to unlock it.</string>
     <string name="needPuk2">Type PUK2 to unblock SIM card.</string>
+    <!-- Displayed when user attempts to change SIM PIN1 without enabling PIN1. -->
+    <string name="enablePin">Unsuccessful, enable SIM/RUIM Lock.</string>
+    <!-- Displayed when a SIM PIN/PUK is entered incorrectly. -->
+    <plurals name="pinpuk_attempts">
+        <item quantity="one">You have <xliff:g id="number">%d</xliff:g> remaining attempt before SIM is locked.</item>
+        <item quantity="other">You have <xliff:g id="number">%d</xliff:g> remaining attempts before SIM is locked.</item>
+    </plurals>
     <!-- Title for the dialog used to display the user's IMEI number [CHAR LIMIT=10] -->
     <string name="imei">IMEI</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f578694..a5573c9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -55,6 +55,7 @@
   <java-symbol type="id" name="clearDefaultHint" />
   <java-symbol type="id" name="contentPanel" />
   <java-symbol type="id" name="current_scene" />
+  <java-symbol type="id" name="scene_layoutid_cache" />
   <java-symbol type="id" name="customPanel" />
   <java-symbol type="id" name="datePicker" />
   <java-symbol type="id" name="day" />
@@ -105,7 +106,6 @@
   <java-symbol type="id" name="month" />
   <java-symbol type="id" name="month_name" />
   <java-symbol type="id" name="name" />
-  <java-symbol type="id" name="navigationGuard" />
   <java-symbol type="id" name="next" />
   <java-symbol type="id" name="next_button" />
   <java-symbol type="id" name="new_app_action" />
@@ -612,6 +612,7 @@
   <java-symbol type="string" name="more_item_label" />
   <java-symbol type="string" name="needPuk" />
   <java-symbol type="string" name="needPuk2" />
+  <java-symbol type="string" name="enablePin" />
   <java-symbol type="string" name="new_app_action" />
   <java-symbol type="string" name="new_app_description" />
   <java-symbol type="string" name="noApplications" />
@@ -965,6 +966,7 @@
   <java-symbol type="plurals" name="num_minutes_ago" />
   <java-symbol type="plurals" name="num_seconds_ago" />
   <java-symbol type="plurals" name="restr_pin_countdown" />
+  <java-symbol type="plurals" name="pinpuk_attempts" />
 
   <java-symbol type="array" name="carrier_properties" />
   <java-symbol type="array" name="config_data_usage_network_types" />
diff --git a/core/tests/coretests/apks/version_nosys/Android.mk b/core/tests/coretests/apks/version_nosys/Android.mk
new file mode 100644
index 0000000..bbc8e12
--- /dev/null
+++ b/core/tests/coretests/apks/version_nosys/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := version_1_nosys
+LOCAL_AAPT_FLAGS := --version-code 1 --version-name 1.0
+LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/unit_test
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/version_nosys/AndroidManifest.xml b/core/tests/coretests/apks/version_nosys/AndroidManifest.xml
new file mode 100644
index 0000000..46aac38
--- /dev/null
+++ b/core/tests/coretests/apks/version_nosys/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.version_test">
+
+    <!-- Do not ask for this system permission -->
+<!--    <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
+-->
+    <!-- Which permission it uses is not important as long as it's a normal
+         permission -->
+    <uses-permission android:name="android.permission.VIBRATE" />
+
+    <application android:hasCode="false"/>
+</manifest>
diff --git a/core/tests/coretests/apks/version_nosys/res/values/strings.xml b/core/tests/coretests/apks/version_nosys/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/version_nosys/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/version_nosys/src/com/android/frameworks/coretests/version_test/NullProvider.java b/core/tests/coretests/apks/version_nosys/src/com/android/frameworks/coretests/version_test/NullProvider.java
new file mode 100644
index 0000000..f5742f0
--- /dev/null
+++ b/core/tests/coretests/apks/version_nosys/src/com/android/frameworks/coretests/version_test/NullProvider.java
@@ -0,0 +1,39 @@
+package com.android.frameworks.coretests.version_test;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class NullProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "text/plain";
+    }
+}
diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf
index 072b842..c5b9c67 100644
--- a/data/fonts/Roboto-Bold.ttf
+++ b/data/fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf
index 74919ff..0320214 100644
--- a/data/fonts/Roboto-BoldItalic.ttf
+++ b/data/fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf
index 4642d6f..38ba570 100644
--- a/data/fonts/Roboto-Italic.ttf
+++ b/data/fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Light.ttf b/data/fonts/Roboto-Light.ttf
index 13bf13a..271606b 100644
--- a/data/fonts/Roboto-Light.ttf
+++ b/data/fonts/Roboto-Light.ttf
Binary files differ
diff --git a/data/fonts/Roboto-LightItalic.ttf b/data/fonts/Roboto-LightItalic.ttf
index 130672a..17ef355 100644
--- a/data/fonts/Roboto-LightItalic.ttf
+++ b/data/fonts/Roboto-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf
index 0ba95c9..7469063 100644
--- a/data/fonts/Roboto-Regular.ttf
+++ b/data/fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Thin.ttf b/data/fonts/Roboto-Thin.ttf
index 309c22d..74efe4d 100644
--- a/data/fonts/Roboto-Thin.ttf
+++ b/data/fonts/Roboto-Thin.ttf
Binary files differ
diff --git a/data/fonts/Roboto-ThinItalic.ttf b/data/fonts/Roboto-ThinItalic.ttf
index 0b53ba4..f08ea51 100644
--- a/data/fonts/Roboto-ThinItalic.ttf
+++ b/data/fonts/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Bold.ttf b/data/fonts/RobotoCondensed-Bold.ttf
index f0fd409..1252d00 100644
--- a/data/fonts/RobotoCondensed-Bold.ttf
+++ b/data/fonts/RobotoCondensed-Bold.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-BoldItalic.ttf b/data/fonts/RobotoCondensed-BoldItalic.ttf
index e67b02b0..e914a07 100644
--- a/data/fonts/RobotoCondensed-BoldItalic.ttf
+++ b/data/fonts/RobotoCondensed-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Italic.ttf b/data/fonts/RobotoCondensed-Italic.ttf
index a08414b..8a570cf 100644
--- a/data/fonts/RobotoCondensed-Italic.ttf
+++ b/data/fonts/RobotoCondensed-Italic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Regular.ttf b/data/fonts/RobotoCondensed-Regular.ttf
index 713fd30..a16b9cb 100644
--- a/data/fonts/RobotoCondensed-Regular.ttf
+++ b/data/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/land_back.png b/docs/html/distribute/promote/device-art-resources/nexus_5/land_back.png
new file mode 100644
index 0000000..697c017
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/land_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/land_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_5/land_fore.png
new file mode 100644
index 0000000..29aed613
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/land_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/land_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_5/land_shadow.png
new file mode 100644
index 0000000..fad6db1
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/land_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/port_back.png b/docs/html/distribute/promote/device-art-resources/nexus_5/port_back.png
new file mode 100644
index 0000000..b31aac6
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/port_back.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/port_fore.png b/docs/html/distribute/promote/device-art-resources/nexus_5/port_fore.png
new file mode 100644
index 0000000..aed056e
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/port_fore.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/port_shadow.png b/docs/html/distribute/promote/device-art-resources/nexus_5/port_shadow.png
new file mode 100644
index 0000000..b3ae20c
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/port_shadow.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art-resources/nexus_5/thumb.png b/docs/html/distribute/promote/device-art-resources/nexus_5/thumb.png
new file mode 100644
index 0000000..e013e39
--- /dev/null
+++ b/docs/html/distribute/promote/device-art-resources/nexus_5/thumb.png
Binary files differ
diff --git a/docs/html/distribute/promote/device-art.jd b/docs/html/distribute/promote/device-art.jd
index 89231b2..b3b414e 100644
--- a/docs/html/distribute/promote/device-art.jd
+++ b/docs/html/distribute/promote/device-art.jd
@@ -117,6 +117,9 @@
     border-top: 1px solid transparent;
     background: transparent url({@docRoot}assets/images/styles/disclosure_down.png)
                 no-repeat scroll 0 8px;
+    -webkit-transition: border 0.2s;
+       -moz-transition: border 0.2s;
+            transition: border 0.2s;
   }
 
   #archive-expando.expanded {
@@ -124,6 +127,21 @@
     border-top: 1px solid #ccc;
   }
 
+  .device-list.archive {
+    max-height: 0;
+    overflow: hidden;
+    opacity: 0;
+
+    -webkit-transition: max-height 0.2s, opacity 0.2s;
+       -moz-transition: max-height 0.2s, opacity 0.2s;
+            transition: max-height 0.2s, opacity 0.2s;
+  }
+
+  .device-list.archive.expanded {
+    opacity: 1;
+    max-height: 300px;
+  }
+
   #output {
     color: #f44;
     font-style: italic;
@@ -152,17 +170,17 @@
   // Device manifest.
   var DEVICES = [
     {
-      id: 'nexus_4',
-      title: 'Nexus 4',
-      url: 'http://www.google.com/nexus/4/',
-      physicalSize: 4.7,
-      physicalHeight: 5.23,
-      density: 'XHDPI',
+      id: 'nexus_5',
+      title: 'Nexus 5',
+      url: 'http://www.google.com/nexus/5/',
+      physicalSize: 5,
+      physicalHeight: 5.43,
+      density: 'XXHDPI',
       landRes: ['shadow', 'back', 'fore'],
-      landOffset: [349,214],
+      landOffset: [436,306],
       portRes: ['shadow', 'back', 'fore'],
-      portOffset: [213,350],
-      portSize: [768,1280]
+      portOffset: [304,436],
+      portSize: [1080,1920],
     },
     {
       id: 'nexus_7',
@@ -221,6 +239,20 @@
       archived: true
     },
     {
+      id: 'nexus_4',
+      title: 'Nexus 4',
+      url: 'http://www.google.com/nexus/4/',
+      physicalSize: 4.7,
+      physicalHeight: 5.27,
+      density: 'XHDPI',
+      landRes: ['shadow', 'back', 'fore'],
+      landOffset: [349,214],
+      portRes: ['shadow', 'back', 'fore'],
+      portOffset: [213,350],
+      portSize: [768,1280],
+      archived: true
+    },
+    {
       id: 'galaxy_nexus',
       title: 'Galaxy Nexus',
       url: 'http://www.android.com/devices/detail/galaxy-nexus',
@@ -321,7 +353,6 @@
     $('#output').html(MSG_NO_INPUT_IMAGE);
 
     $('#frame-customizations').hide();
-    $('.device-list.archive').hide();
 
     $('#output-shadow, #output-glare').click(function() {
       createFrame();
@@ -360,10 +391,10 @@
     $('#archive-expando').click(function() {
       if ($(this).hasClass('expanded')) {
         $(this).removeClass('expanded');
-        $('.device-list.archive').hide();
+        $('.device-list.archive').removeClass('expanded');
       } else {
         $(this).addClass('expanded');
-        $('.device-list.archive').show();
+        $('.device-list.archive').addClass('expanded');
       }
       return false;
     });
diff --git a/docs/html/training/displaying-bitmaps/cache-bitmap.jd b/docs/html/training/displaying-bitmaps/cache-bitmap.jd
index 25efe1e..ad084c2 100644
--- a/docs/html/training/displaying-bitmaps/cache-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/cache-bitmap.jd
@@ -346,6 +346,7 @@
         RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
         if (fragment == null) {
             fragment = new RetainFragment();
+            fm.beginTransaction().add(fragment, TAG).commit();
         }
         return fragment;
     }
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 07d91ac..59d411d 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -1476,16 +1476,17 @@
      * Set the new remote control receiver at the top of the RC focus stack.
      * Called synchronized on mAudioFocusLock, then mRCStack
      * precondition: mediaIntent != null
+     * @return true if mRCStack was changed, false otherwise
      */
-    private void pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent, ComponentName target,
-            IBinder token) {
+    private boolean pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent,
+            ComponentName target, IBinder token) {
         // already at top of stack?
         if (!mRCStack.empty() && mRCStack.peek().mMediaIntent.equals(mediaIntent)) {
-            return;
+            return false;
         }
         if (mAppOps.noteOp(AppOpsManager.OP_TAKE_MEDIA_BUTTONS, Binder.getCallingUid(),
                 mediaIntent.getCreatorPackage()) != AppOpsManager.MODE_ALLOWED) {
-            return;
+            return false;
         }
         RemoteControlStackEntry rcse = null;
         boolean wasInsideStack = false;
@@ -1513,6 +1514,9 @@
             mEventHandler.sendMessage( mEventHandler.obtainMessage(
                     MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
         }
+
+        // RC stack was modified
+        return true;
     }
 
     /**
@@ -1856,9 +1860,10 @@
 
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
-                pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token);
-                // new RC client, assume every type of information shall be queried
-                checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
+                if (pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token)) {
+                    // new RC client, assume every type of information shall be queried
+                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
+                }
             }
         }
     }
@@ -1925,6 +1930,7 @@
         int rccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
+                boolean wasCurrentRcController = isCurrentRcController(mediaIntent);
                 // store the new display information
                 try {
                     for (int index = mRCStack.size()-1; index >= 0; index--) {
@@ -1971,9 +1977,9 @@
                     Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
                 }
 
-                // if the eventReceiver is at the top of the stack
+                // if the eventReceiver is now at the top of the stack but wasn't before
                 // then check for potential refresh of the remote controls
-                if (isCurrentRcController(mediaIntent)) {
+                if (isCurrentRcController(mediaIntent) && !wasCurrentRcController) {
                     checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
                 }
             }//synchronized(mRCStack)
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 12f7bd9..1e1ef8c 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -120,8 +120,6 @@
             .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
 
     /**
-     * @hide
-     * CANDIDATE FOR PUBLIC API
      * UUID for Loudness Enhancer
      */
     public static final UUID EFFECT_TYPE_LOUDNESS_ENHANCER = UUID
diff --git a/media/java/android/media/audiofx/LoudnessEnhancer.java b/media/java/android/media/audiofx/LoudnessEnhancer.java
index eb2fb75..7dc4175 100644
--- a/media/java/android/media/audiofx/LoudnessEnhancer.java
+++ b/media/java/android/media/audiofx/LoudnessEnhancer.java
@@ -65,7 +65,6 @@
     private final Object mParamListenerLock = new Object();
 
     /**
-     * @hide
      * Class constructor.
      * @param audioSession system-wide unique audio session identifier. The LoudnessEnhancer
      * will be attached to the MediaPlayer or AudioTrack in the same audio session.
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 6faf7f8..179bcd1 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -50,6 +50,14 @@
             android:authorities="com.android.documentsui.recents"
             android:exported="false" />
 
+        <receiver android:name=".PackageReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
+                <action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
+                <data android:scheme="package" />
+            </intent-filter>
+        </receiver>
+
         <!-- TODO: remove when we have real clients -->
         <activity android:name=".TestActivity" android:enabled="false">
             <intent-filter>
diff --git a/packages/DocumentsUI/res/layout/fragment_save.xml b/packages/DocumentsUI/res/layout/fragment_save.xml
index 891f0a0..d601194 100644
--- a/packages/DocumentsUI/res/layout/fragment_save.xml
+++ b/packages/DocumentsUI/res/layout/fragment_save.xml
@@ -51,15 +51,31 @@
             android:singleLine="true"
             android:selectAllOnFocus="true" />
 
-        <Button
-            android:id="@android:id/button1"
+        <FrameLayout
             android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:background="?android:attr/selectableItemBackground"
-            android:text="@string/menu_save"
-            android:textAllCaps="true"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:padding="8dp" />
+            android:layout_height="match_parent">
+
+            <Button
+                android:id="@android:id/button1"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:background="?android:attr/selectableItemBackground"
+                android:text="@string/menu_save"
+                android:textAllCaps="true"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:padding="8dp" />
+
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:visibility="gone"
+                android:indeterminate="true"
+                android:padding="8dp"
+                style="?android:attr/progressBarStyle" />
+
+        </FrameLayout>
 
     </LinearLayout>
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 90be197..ba8c35f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -95,6 +95,11 @@
         }
 
         @Override
+        protected void onPreExecute() {
+            mActivity.setPending(true);
+        }
+
+        @Override
         protected DocumentInfo doInBackground(Void... params) {
             final ContentResolver resolver = mActivity.getContentResolver();
             ContentProviderClient client = null;
@@ -120,6 +125,8 @@
             } else {
                 Toast.makeText(mActivity, R.string.create_error, Toast.LENGTH_SHORT).show();
             }
+
+            mActivity.setPending(false);
         }
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 1f3901c..fa8bc9d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -76,6 +76,7 @@
 import android.widget.Toast;
 
 import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.ProviderExecutor.Preemptable;
 import com.android.documentsui.RecentsProvider.StateColumns;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
@@ -528,7 +529,7 @@
             if (iconThumb != null) {
                 final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
                 if (oldTask != null) {
-                    oldTask.reallyCancel();
+                    oldTask.preempt();
                     iconThumb.setTag(null);
                 }
             }
@@ -794,7 +795,7 @@
 
             final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
             if (oldTask != null) {
-                oldTask.reallyCancel();
+                oldTask.preempt();
                 iconThumb.setTag(null);
             }
 
@@ -818,7 +819,7 @@
                     final ThumbnailAsyncTask task = new ThumbnailAsyncTask(
                             uri, iconMime, iconThumb, mThumbSize);
                     iconThumb.setTag(task);
-                    task.executeOnExecutor(ProviderExecutor.forAuthority(docAuthority));
+                    ProviderExecutor.forAuthority(docAuthority).execute(task);
                 }
             }
 
@@ -988,7 +989,8 @@
         }
     }
 
-    private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
+    private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap>
+            implements Preemptable {
         private final Uri mUri;
         private final ImageView mIconMime;
         private final ImageView mIconThumb;
@@ -1004,7 +1006,8 @@
             mSignal = new CancellationSignal();
         }
 
-        public void reallyCancel() {
+        @Override
+        public void preempt() {
             cancel(false);
             mSignal.cancel();
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index d675e8d..a9278d7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -661,6 +661,13 @@
         DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
     }
 
+    public void setPending(boolean pending) {
+        final SaveFragment save = SaveFragment.get(getFragmentManager());
+        if (save != null) {
+            save.setPending(pending);
+        }
+    }
+
     @Override
     public void onBackPressed() {
         if (!mState.stackTouched) {
@@ -1051,6 +1058,11 @@
         }
 
         @Override
+        protected void onPreExecute() {
+            setPending(true);
+        }
+
+        @Override
         protected Uri doInBackground(Void... params) {
             final ContentResolver resolver = getContentResolver();
             final DocumentInfo cwd = getCurrentDirectory();
@@ -1083,6 +1095,8 @@
                 Toast.makeText(DocumentsActivity.this, R.string.save_error, Toast.LENGTH_SHORT)
                         .show();
             }
+
+            setPending(false);
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 6b46e3a..547e343 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -75,6 +75,7 @@
         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
         packageFilter.addDataScheme("package");
         registerReceiver(mCacheReceiver, packageFilter);
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java
new file mode 100644
index 0000000..aef63af
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/PackageReceiver.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.android.documentsui;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+/**
+ * Clean up {@link RecentsProvider} when packages are removed.
+ */
+public class PackageReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final ContentResolver resolver = context.getContentResolver();
+
+        final String action = intent.getAction();
+        if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+            resolver.call(RecentsProvider.buildRecent(), RecentsProvider.METHOD_PURGE, null, null);
+
+        } else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
+            final Uri data = intent.getData();
+            if (data != null) {
+                final String packageName = data.getSchemeSpecificPart();
+                resolver.call(RecentsProvider.buildRecent(), RecentsProvider.METHOD_PURGE_PACKAGE,
+                        packageName, null);
+            }
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
index 2105cb41..f94aebd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -16,10 +16,15 @@
 
 package com.android.documentsui;
 
+import android.os.AsyncTask;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
+import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -29,7 +34,7 @@
     @GuardedBy("sExecutors")
     private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap();
 
-    public static Executor forAuthority(String authority) {
+    public static ProviderExecutor forAuthority(String authority) {
         synchronized (sExecutors) {
             ProviderExecutor executor = sExecutors.get(authority);
             if (executor == null) {
@@ -42,10 +47,54 @@
         }
     }
 
+    public interface Preemptable {
+        void preempt();
+    }
+
     private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();
 
+    private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList();
+
+    private void preempt() {
+        synchronized (mPreemptable) {
+            int count = 0;
+            for (WeakReference<Preemptable> ref : mPreemptable) {
+                final Preemptable p = ref.get();
+                if (p != null) {
+                    count++;
+                    p.preempt();
+                }
+            }
+            mPreemptable.clear();
+        }
+    }
+
+    /**
+     * Execute the given task. If given task is not {@link Preemptable}, it will
+     * preempt all outstanding preemptable tasks.
+     */
+    public <P> void execute(AsyncTask<P, ?, ?> task, P... params) {
+        if (task instanceof Preemptable) {
+            synchronized (mPreemptable) {
+                mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task));
+            }
+            task.executeOnExecutor(mNonPreemptingExecutor, params);
+        } else {
+            task.executeOnExecutor(this, params);
+        }
+    }
+
+    private Executor mNonPreemptingExecutor = new Executor() {
+        @Override
+        public void execute(Runnable command) {
+            Preconditions.checkNotNull(command);
+            mQueue.add(command);
+        }
+    };
+
     @Override
     public void execute(Runnable command) {
+        preempt();
         Preconditions.checkNotNull(command);
         mQueue.add(command);
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index 4313fa7..f6e4349 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -16,24 +16,40 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
+
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
 import android.content.UriMatcher;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.net.Uri;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 import android.text.format.DateUtils;
 import android.util.Log;
 
+import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.DurableUtils;
+import com.android.internal.util.Predicate;
+import com.google.android.collect.Sets;
+
+import libcore.io.IoUtils;
+
+import java.io.IOException;
+import java.util.Set;
+
 public class RecentsProvider extends ContentProvider {
     private static final String TAG = "RecentsProvider";
 
-    public static final long MAX_HISTORY_IN_MILLIS = 45 * DateUtils.DAY_IN_MILLIS;
+    private static final long MAX_HISTORY_IN_MILLIS = 45 * DateUtils.DAY_IN_MILLIS;
 
     private static final String AUTHORITY = "com.android.documentsui.recents";
 
@@ -43,6 +59,9 @@
     private static final int URI_STATE = 2;
     private static final int URI_RESUME = 3;
 
+    public static final String METHOD_PURGE = "purge";
+    public static final String METHOD_PURGE_PACKAGE = "purgePackage";
+
     static {
         sMatcher.addURI(AUTHORITY, "recent", URI_RECENT);
         // state/authority/rootId/docId
@@ -231,4 +250,116 @@
     public int delete(Uri uri, String selection, String[] selectionArgs) {
         throw new UnsupportedOperationException("Unsupported Uri " + uri);
     }
+
+    @Override
+    public Bundle call(String method, String arg, Bundle extras) {
+        if (METHOD_PURGE.equals(method)) {
+            // Purge references to unknown authorities
+            final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+            final Set<String> knownAuth = Sets.newHashSet();
+            for (ResolveInfo info : getContext()
+                    .getPackageManager().queryIntentContentProviders(intent, 0)) {
+                knownAuth.add(info.providerInfo.authority);
+            }
+
+            purgeByAuthority(new Predicate<String>() {
+                @Override
+                public boolean apply(String authority) {
+                    // Purge unknown authorities
+                    return !knownAuth.contains(authority);
+                }
+            });
+
+            return null;
+
+        } else if (METHOD_PURGE_PACKAGE.equals(method)) {
+            // Purge references to authorities in given package
+            final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+            intent.setPackage(arg);
+            final Set<String> packageAuth = Sets.newHashSet();
+            for (ResolveInfo info : getContext()
+                    .getPackageManager().queryIntentContentProviders(intent, 0)) {
+                packageAuth.add(info.providerInfo.authority);
+            }
+
+            if (!packageAuth.isEmpty()) {
+                purgeByAuthority(new Predicate<String>() {
+                    @Override
+                    public boolean apply(String authority) {
+                        // Purge authority matches
+                        return packageAuth.contains(authority);
+                    }
+                });
+            }
+
+            return null;
+
+        } else {
+            return super.call(method, arg, extras);
+        }
+    }
+
+    /**
+     * Purge all internal data whose authority matches the given
+     * {@link Predicate}.
+     */
+    private void purgeByAuthority(Predicate<String> predicate) {
+        final SQLiteDatabase db = mHelper.getWritableDatabase();
+        final DocumentStack stack = new DocumentStack();
+
+        Cursor cursor = db.query(TABLE_RECENT, null, null, null, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                try {
+                    final byte[] rawStack = cursor.getBlob(
+                            cursor.getColumnIndex(RecentColumns.STACK));
+                    DurableUtils.readFromArray(rawStack, stack);
+
+                    if (stack.root != null && predicate.apply(stack.root.authority)) {
+                        final String key = getCursorString(cursor, RecentColumns.KEY);
+                        db.delete(TABLE_RECENT, RecentColumns.KEY + "=?", new String[] { key });
+                    }
+                } catch (IOException ignored) {
+                }
+            }
+        } finally {
+            IoUtils.closeQuietly(cursor);
+        }
+
+        cursor = db.query(TABLE_STATE, new String[] {
+                StateColumns.AUTHORITY }, null, null, StateColumns.AUTHORITY, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                final String authority = getCursorString(cursor, StateColumns.AUTHORITY);
+                if (predicate.apply(authority)) {
+                    db.delete(TABLE_STATE, StateColumns.AUTHORITY + "=?", new String[] {
+                            authority });
+                    Log.d(TAG, "Purged state for " + authority);
+                }
+            }
+        } finally {
+            IoUtils.closeQuietly(cursor);
+        }
+
+        cursor = db.query(TABLE_RESUME, null, null, null, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                try {
+                    final byte[] rawStack = cursor.getBlob(
+                            cursor.getColumnIndex(ResumeColumns.STACK));
+                    DurableUtils.readFromArray(rawStack, stack);
+
+                    if (stack.root != null && predicate.apply(stack.root.authority)) {
+                        final String packageName = getCursorString(
+                                cursor, ResumeColumns.PACKAGE_NAME);
+                        db.delete(TABLE_RESUME, ResumeColumns.PACKAGE_NAME + "=?",
+                                new String[] { packageName });
+                    }
+                } catch (IOException ignored) {
+                }
+            }
+        } finally {
+            IoUtils.closeQuietly(cursor);
+        }
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index b98e1ee..f6b43c7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -60,8 +60,8 @@
 public class RootsCache {
     private static final boolean LOGD = true;
 
-    // TODO: cache roots in local provider to avoid spinning up backends
-    // TODO: root updates should trigger UI refresh
+    public static final Uri sNotificationUri = Uri.parse(
+            "content://com.android.documentsui.roots/");
 
     private final Context mContext;
     private final ContentObserver mObserver;
@@ -201,6 +201,7 @@
                 mStoppedAuthorities = mTaskStoppedAuthorities;
             }
             mFirstLoad.countDown();
+            resolver.notifyChange(sNotificationUri, null, false);
             return null;
         }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index fdbc3ab..58c5daf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
+
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
@@ -25,7 +27,9 @@
 import android.content.Loader;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.net.Uri;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.view.LayoutInflater;
@@ -33,6 +37,7 @@
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.ListView;
@@ -133,6 +138,13 @@
         final State state = ((DocumentsActivity) context).getDisplayState();
         state.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(context);
 
+        if (state.action == ACTION_GET_CONTENT) {
+            mList.setOnItemLongClickListener(mItemLongClickListener);
+        } else {
+            mList.setOnItemLongClickListener(null);
+            mList.setLongClickable(false);
+        }
+
         getLoaderManager().restartLoader(2, null, mCallbacks);
     }
 
@@ -152,6 +164,13 @@
         }
     }
 
+    private void showAppDetails(ResolveInfo ri) {
+        final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        intent.setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+        startActivity(intent);
+    }
+
     private OnItemClickListener mItemListener = new OnItemClickListener() {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
@@ -167,6 +186,19 @@
         }
     };
 
+    private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() {
+        @Override
+        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+            final Item item = mAdapter.getItem(position);
+            if (item instanceof AppItem) {
+                showAppDetails(((AppItem) item).info);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    };
+
     private static abstract class Item {
         private final int mLayoutId;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
index 7108971..8d37cdf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
@@ -25,6 +25,8 @@
 import java.util.Collection;
 
 public class RootsLoader extends AsyncTaskLoader<Collection<RootInfo>> {
+    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
+
     private final RootsCache mRoots;
     private final State mState;
 
@@ -34,6 +36,9 @@
         super(context);
         mRoots = roots;
         mState = state;
+
+        getContext().getContentResolver()
+                .registerContentObserver(RootsCache.sNotificationUri, false, mObserver);
     }
 
     @Override
@@ -77,5 +82,7 @@
         onStopLoading();
 
         mResult = null;
+
+        getContext().getContentResolver().unregisterContentObserver(mObserver);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index 23e047c..9d70c51 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -30,6 +30,7 @@
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ImageView;
+import android.widget.ProgressBar;
 
 import com.android.documentsui.model.DocumentInfo;
 
@@ -42,6 +43,7 @@
     private DocumentInfo mReplaceTarget;
     private EditText mDisplayName;
     private Button mSave;
+    private ProgressBar mProgress;
     private boolean mIgnoreNextEdit;
 
     private static final String EXTRA_MIME_TYPE = "mime_type";
@@ -83,6 +85,8 @@
         mSave.setOnClickListener(mSaveListener);
         mSave.setEnabled(false);
 
+        mProgress = (ProgressBar) view.findViewById(android.R.id.progress);
+
         return view;
     }
 
@@ -92,7 +96,6 @@
             if (mIgnoreNextEdit) {
                 mIgnoreNextEdit = false;
             } else {
-                Log.d(TAG, "onTextChanged!");
                 mReplaceTarget = null;
             }
         }
@@ -140,4 +143,9 @@
     public void setSaveEnabled(boolean enabled) {
         mSave.setEnabled(enabled);
     }
+
+    public void setPending(boolean pending) {
+        mSave.setVisibility(pending ? View.INVISIBLE : View.VISIBLE);
+        mProgress.setVisibility(pending ? View.VISIBLE : View.GONE);
+    }
 }
diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml
index 99a42600..5169fef 100644
--- a/packages/ExternalStorageProvider/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/AndroidManifest.xml
@@ -16,6 +16,14 @@
             </intent-filter>
         </provider>
 
+        <receiver android:name=".MountReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.MEDIA_MOUNTED" />
+                <action android:name="android.intent.action.MEDIA_UNMOUNTED" />
+                <data android:scheme="file" />
+            </intent-filter>
+        </receiver>
+
         <!-- TODO: find a better place for tests to live -->
         <provider
             android:name=".TestDocumentsProvider"
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 11ff2d8..d42354f 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -16,21 +16,25 @@
 
 package com.android.externalstorage;
 
+import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.database.MatrixCursor.RowBuilder;
 import android.graphics.Point;
-import android.media.ExifInterface;
 import android.os.CancellationSignal;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
+import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
-import android.provider.DocumentsContract;
 import android.provider.DocumentsProvider;
+import android.util.Log;
 import android.webkit.MimeTypeMap;
 
+import com.android.internal.annotations.GuardedBy;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -45,6 +49,8 @@
 public class ExternalStorageProvider extends DocumentsProvider {
     private static final String TAG = "ExternalStorage";
 
+    public static final String AUTHORITY = "com.android.externalstorage.documents";
+
     // docId format: root:path/to/file
 
     private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
@@ -64,42 +70,91 @@
         public String docId;
     }
 
+    private static final String ROOT_ID_PRIMARY_EMULATED = "primary";
+
+    private StorageManager mStorageManager;
+
+    private final Object mRootsLock = new Object();
+
+    @GuardedBy("mRootsLock")
     private ArrayList<RootInfo> mRoots;
+    @GuardedBy("mRootsLock")
     private HashMap<String, RootInfo> mIdToRoot;
+    @GuardedBy("mRootsLock")
     private HashMap<String, File> mIdToPath;
 
     @Override
     public boolean onCreate() {
+        mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
+
         mRoots = Lists.newArrayList();
         mIdToRoot = Maps.newHashMap();
         mIdToPath = Maps.newHashMap();
 
-        // TODO: support multiple storage devices, requiring that volume serial
-        // number be burned into rootId so we can identify files from different
-        // volumes. currently we only use a static rootId for emulated storage,
-        // since that storage never changes.
-        if (!Environment.isExternalStorageEmulated()) return true;
-
-        try {
-            final String rootId = "primary";
-            final File path = Environment.getExternalStorageDirectory();
-            mIdToPath.put(rootId, path);
-
-            final RootInfo root = new RootInfo();
-            root.rootId = rootId;
-            root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
-                    | Root.FLAG_SUPPORTS_SEARCH;
-            root.title = getContext().getString(R.string.root_internal_storage);
-            root.docId = getDocIdForFile(path);
-            mRoots.add(root);
-            mIdToRoot.put(rootId, root);
-        } catch (FileNotFoundException e) {
-            throw new IllegalStateException(e);
-        }
+        updateVolumes();
 
         return true;
     }
 
+    public void updateVolumes() {
+        synchronized (mRootsLock) {
+            updateVolumesLocked();
+        }
+    }
+
+    private void updateVolumesLocked() {
+        mRoots.clear();
+        mIdToPath.clear();
+        mIdToRoot.clear();
+
+        final StorageVolume[] volumes = mStorageManager.getVolumeList();
+        for (StorageVolume volume : volumes) {
+            final boolean mounted = Environment.MEDIA_MOUNTED.equals(volume.getState())
+                    || Environment.MEDIA_MOUNTED_READ_ONLY.equals(volume.getState());
+            if (!mounted) continue;
+
+            final String rootId;
+            if (volume.isPrimary() && volume.isEmulated()) {
+                rootId = ROOT_ID_PRIMARY_EMULATED;
+            } else if (volume.getUuid() != null) {
+                rootId = volume.getUuid();
+            } else {
+                Log.d(TAG, "Missing UUID for " + volume.getPath() + "; skipping");
+                continue;
+            }
+
+            if (mIdToPath.containsKey(rootId)) {
+                Log.w(TAG, "Duplicate UUID " + rootId + "; skipping");
+                continue;
+            }
+
+            try {
+                final File path = volume.getPathFile();
+                mIdToPath.put(rootId, path);
+
+                final RootInfo root = new RootInfo();
+                root.rootId = rootId;
+                root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
+                        | Root.FLAG_SUPPORTS_SEARCH;
+                if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) {
+                    root.title = getContext().getString(R.string.root_internal_storage);
+                } else {
+                    root.title = volume.getUserLabel();
+                }
+                root.docId = getDocIdForFile(path);
+                mRoots.add(root);
+                mIdToRoot.put(rootId, root);
+            } catch (FileNotFoundException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        Log.d(TAG, "After updating volumes, found " + mRoots.size() + " active roots");
+
+        getContext().getContentResolver()
+                .notifyChange(DocumentsContract.buildRootsUri(AUTHORITY), null, false);
+    }
+
     private static String[] resolveRootProjection(String[] projection) {
         return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
     }
@@ -113,11 +168,13 @@
 
         // Find the most-specific root path
         Map.Entry<String, File> mostSpecific = null;
-        for (Map.Entry<String, File> root : mIdToPath.entrySet()) {
-            final String rootPath = root.getValue().getPath();
-            if (path.startsWith(rootPath) && (mostSpecific == null
-                    || rootPath.length() > mostSpecific.getValue().getPath().length())) {
-                mostSpecific = root;
+        synchronized (mRootsLock) {
+            for (Map.Entry<String, File> root : mIdToPath.entrySet()) {
+                final String rootPath = root.getValue().getPath();
+                if (path.startsWith(rootPath) && (mostSpecific == null
+                        || rootPath.length() > mostSpecific.getValue().getPath().length())) {
+                    mostSpecific = root;
+                }
             }
         }
 
@@ -143,7 +200,10 @@
         final String tag = docId.substring(0, splitIndex);
         final String path = docId.substring(splitIndex + 1);
 
-        File target = mIdToPath.get(tag);
+        File target;
+        synchronized (mRootsLock) {
+            target = mIdToPath.get(tag);
+        }
         if (target == null) {
             throw new FileNotFoundException("No root for " + tag);
         }
@@ -199,16 +259,18 @@
     @Override
     public Cursor queryRoots(String[] projection) throws FileNotFoundException {
         final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
-        for (String rootId : mIdToPath.keySet()) {
-            final RootInfo root = mIdToRoot.get(rootId);
-            final File path = mIdToPath.get(rootId);
+        synchronized (mRootsLock) {
+            for (String rootId : mIdToPath.keySet()) {
+                final RootInfo root = mIdToRoot.get(rootId);
+                final File path = mIdToPath.get(rootId);
 
-            final RowBuilder row = result.newRow();
-            row.add(Root.COLUMN_ROOT_ID, root.rootId);
-            row.add(Root.COLUMN_FLAGS, root.flags);
-            row.add(Root.COLUMN_TITLE, root.title);
-            row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
-            row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
+                final RowBuilder row = result.newRow();
+                row.add(Root.COLUMN_ROOT_ID, root.rootId);
+                row.add(Root.COLUMN_FLAGS, root.flags);
+                row.add(Root.COLUMN_TITLE, root.title);
+                row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
+                row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
+            }
         }
         return result;
     }
@@ -277,7 +339,11 @@
     public Cursor querySearchDocuments(String rootId, String query, String[] projection)
             throws FileNotFoundException {
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-        final File parent = mIdToPath.get(rootId);
+
+        final File parent;
+        synchronized (mRootsLock) {
+            parent = mIdToPath.get(rootId);
+        }
 
         final LinkedList<File> pending = new LinkedList<File>();
         pending.add(parent);
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/MountReceiver.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/MountReceiver.java
new file mode 100644
index 0000000..8a6c7d6
--- /dev/null
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/MountReceiver.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.externalstorage;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentProviderClient;
+import android.content.Context;
+import android.content.Intent;
+
+public class MountReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final ContentProviderClient client = context.getContentResolver()
+                .acquireContentProviderClient(ExternalStorageProvider.AUTHORITY);
+        try {
+            ((ExternalStorageProvider) client.getLocalContentProvider()).updateVolumes();
+        } finally {
+            ContentProviderClient.releaseQuietly(client);
+        }
+    }
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
index 0caddcc..af6ff01 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
@@ -33,6 +33,7 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.CancellationSignal.OnCancelListener;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
 import android.provider.DocumentsContract;
@@ -54,8 +55,9 @@
 public class TestDocumentsProvider extends DocumentsProvider {
     private static final String TAG = "TestDocuments";
 
+    private static final boolean LAG = false;
+
     private static final boolean ROOTS_WEDGE = false;
-    private static final boolean ROOTS_LAG = false;
     private static final boolean ROOTS_CRASH = false;
     private static final boolean ROOTS_REFRESH = false;
 
@@ -105,8 +107,8 @@
     public Cursor queryRoots(String[] projection) throws FileNotFoundException {
         Log.d(TAG, "Someone asked for our roots!");
 
-        if (ROOTS_WEDGE) SystemClock.sleep(Integer.MAX_VALUE);
-        if (ROOTS_LAG) SystemClock.sleep(3000);
+        if (LAG) lagUntilCanceled(null);
+        if (ROOTS_WEDGE) wedgeUntilCanceled(null);
         if (ROOTS_CRASH) System.exit(12);
 
         if (ROOTS_REFRESH) {
@@ -125,7 +127,7 @@
         final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
         final RowBuilder row = result.newRow();
         row.add(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
-        row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS | Root.FLAG_SUPPORTS_CREATE);
         row.add(Root.COLUMN_TITLE, "_Test title which is really long");
         row.add(Root.COLUMN_SUMMARY,
                 SystemClock.elapsedRealtime() + " summary which is also super long text");
@@ -137,6 +139,7 @@
     @Override
     public Cursor queryDocument(String documentId, String[] projection)
             throws FileNotFoundException {
+        if (LAG) lagUntilCanceled(null);
         if (DOCUMENT_CRASH) System.exit(12);
 
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
@@ -144,6 +147,14 @@
         return result;
     }
 
+    @Override
+    public String createDocument(String parentDocumentId, String mimeType, String displayName)
+            throws FileNotFoundException {
+        if (LAG) lagUntilCanceled(null);
+
+        return super.createDocument(parentDocumentId, mimeType, displayName);
+    }
+
     /**
      * Holds any outstanding or finished "network" fetching.
      */
@@ -209,6 +220,7 @@
             String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
 
+        if (LAG) lagUntilCanceled(null);
         if (CHILD_WEDGE) SystemClock.sleep(Integer.MAX_VALUE);
         if (CHILD_CRASH) System.exit(12);
 
@@ -228,7 +240,7 @@
 
         if (THUMB_HUNDREDS) {
             for (int i = 0; i < 256; i++) {
-                includeFile(result, "i maded u an picshure", Document.FLAG_SUPPORTS_THUMBNAIL);
+                includeFile(result, "i maded u an picshure" + i, Document.FLAG_SUPPORTS_THUMBNAIL);
             }
         }
 
@@ -278,7 +290,8 @@
     public Cursor queryRecentDocuments(String rootId, String[] projection)
             throws FileNotFoundException {
 
-        if (RECENT_WEDGE) SystemClock.sleep(Integer.MAX_VALUE);
+        if (LAG) lagUntilCanceled(null);
+        if (RECENT_WEDGE) wedgeUntilCanceled(null);
 
         // Pretend to take a super long time to respond
         SystemClock.sleep(3000);
@@ -292,6 +305,7 @@
     @Override
     public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
             throws FileNotFoundException {
+        if (LAG) lagUntilCanceled(null);
         throw new FileNotFoundException();
     }
 
@@ -299,6 +313,7 @@
     public AssetFileDescriptor openDocumentThumbnail(
             String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
 
+        if (LAG) lagUntilCanceled(signal);
         if (THUMB_WEDGE) wedgeUntilCanceled(signal);
         if (THUMB_CRASH) System.exit(12);
 
@@ -339,15 +354,34 @@
         return true;
     }
 
+    private static void lagUntilCanceled(CancellationSignal signal) {
+        waitForCancelOrTimeout(signal, 1500);
+    }
+
     private static void wedgeUntilCanceled(CancellationSignal signal) {
+        waitForCancelOrTimeout(signal, Integer.MAX_VALUE);
+    }
+
+    private static void waitForCancelOrTimeout(
+            final CancellationSignal signal, long timeoutMillis) {
         if (signal != null) {
-            while (true) {
-                signal.throwIfCanceled();
-                SystemClock.sleep(500);
-            }
-        } else {
-            Log.w(TAG, "WEDGING WITHOUT A CANCELLATIONSIGNAL");
-            SystemClock.sleep(Integer.MAX_VALUE);
+            final Thread blocked = Thread.currentThread();
+            signal.setOnCancelListener(new OnCancelListener() {
+                @Override
+                public void onCancel() {
+                    blocked.interrupt();
+                }
+            });
+            signal.throwIfCanceled();
+        }
+
+        try {
+            Thread.sleep(timeoutMillis);
+        } catch (InterruptedException e) {
+        }
+
+        if (signal != null) {
+            signal.throwIfCanceled();
         }
     }
 
@@ -360,6 +394,7 @@
 
         if (MY_DOC_ID.equals(docId)) {
             row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
+            row.add(Document.COLUMN_FLAGS, Document.FLAG_DIR_SUPPORTS_CREATE);
         } else if (MY_DOC_NULL.equals(docId)) {
             // No MIME type
         } else {
diff --git a/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_forgotpassword_normal.png b/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_forgotpassword_normal.png
deleted file mode 100644
index 6402d3d..0000000
--- a/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_forgotpassword_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_forgotpassword_pressed.png b/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_forgotpassword_pressed.png
deleted file mode 100644
index 83be046..0000000
--- a/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_forgotpassword_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_forgotpassword_normal.png b/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_forgotpassword_normal.png
deleted file mode 100644
index a7e063a..0000000
--- a/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_forgotpassword_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_forgotpassword_pressed.png b/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_forgotpassword_pressed.png
deleted file mode 100644
index 53af5a5..0000000
--- a/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_forgotpassword_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_forgotpassword_normal.png b/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_forgotpassword_normal.png
deleted file mode 100644
index e4172ce..0000000
--- a/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_forgotpassword_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_forgotpassword_pressed.png b/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_forgotpassword_pressed.png
deleted file mode 100644
index e2c7621..0000000
--- a/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_forgotpassword_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable/lockscreen_forgot_password_button.xml b/packages/Keyguard/res/drawable/lockscreen_forgot_password_button.xml
deleted file mode 100644
index 6c081bf..0000000
--- a/packages/Keyguard/res/drawable/lockscreen_forgot_password_button.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="true" android:drawable="@drawable/ic_lockscreen_forgotpassword_normal" />
-    <item android:state_pressed="true" android:drawable="@drawable/ic_lockscreen_forgotpassword_pressed" />
-    <item android:drawable="@drawable/ic_lockscreen_forgotpassword_normal" />
-</selector>
diff --git a/packages/Keyguard/res/layout-land/keyguard_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
index eeb9ee7..9f1c1f0 100644
--- a/packages/Keyguard/res/layout-land/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
@@ -60,6 +60,8 @@
             android:id="@+id/keyguard_security_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             androidprv:layout_childType="challenge"
             androidprv:layout_centerWithinArea="0.55">
             <com.android.keyguard.KeyguardSecurityViewFlipper
diff --git a/packages/Keyguard/res/layout-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
index 8498dcf..136b296 100644
--- a/packages/Keyguard/res/layout-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
@@ -31,7 +31,8 @@
     <com.android.keyguard.SlidingChallengeLayout
         android:id="@+id/sliding_layout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="match_parent"
+        android:clipChildren="false">
 
         <FrameLayout
             android:layout_width="match_parent"
@@ -64,6 +65,8 @@
             android:id="@+id/keyguard_security_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             androidprv:layout_maxHeight="@dimen/keyguard_security_height"
             androidprv:layout_childType="challenge"
             android:padding="0dp"
diff --git a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
index 77bc9b5..85f6b6d 100644
--- a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -61,6 +61,8 @@
             android:id="@+id/keyguard_security_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             androidprv:layout_centerWithinArea="0.5"
             androidprv:layout_childType="challenge"
             android:layout_gravity="center_horizontal|bottom">
diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
index 313fe9f..8be15cb 100644
--- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
@@ -42,7 +42,7 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="-10dip"
+        android:layout_marginTop="@dimen/eca_overlap"
         style="?android:attr/buttonBarStyle"
         android:orientation="horizontal"
         android:gravity="center"
@@ -66,12 +66,10 @@
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:drawableLeft="@drawable/lockscreen_forgot_password_button"
             style="?android:attr/buttonBarButtonStyle"
             android:textSize="@dimen/kg_status_line_font_size"
             android:textColor="?android:attr/textColorSecondary"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:drawablePadding="8dip"
             android:visibility="gone"
             android:textAllCaps="@bool/kg_use_all_caps" />
     </LinearLayout>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index fa778b3..0761e0e 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -20,14 +20,14 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"اكتب رمز رقم التعريف الشخصي"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"اكتب رمز PUK ورمز رقم التعريف الشخصي الجديد"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"اكتب رمز رمز PIN"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"اكتب رمز PUK ورمز رمز PIN الجديد"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"رمز PUK"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"رمز رقم التعريف الشخصي الجديد"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"رمز رمز PIN الجديد"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"المس لكتابة كلمة المرور"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"اكتب كلمة المرور لإلغاء التأمين"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"اكتب رقم التعريف الشخصي لإلغاء التأمين"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"رقم التعريف الشخصي غير صحيح."</string>
+    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"اكتب رمز PIN لإلغاء التأمين"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"رمز PIN غير صحيح."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"لإلغاء التأمين، اضغط على \"القائمة\" ثم على 0."</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string>
     <string name="keyguard_charged" msgid="3272223906073492454">"تم الشحن"</string>
@@ -62,7 +62,7 @@
     <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"إلغاء القفل باستخدام التمرير."</string>
     <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string>
     <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"تأمين الجهاز بالوجه."</string>
-    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رقم التعريف الشخصي."</string>
+    <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رمز PIN."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"إلغاء القفل باستخدام كلمة المرور."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"منطقة النقش."</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"منطقة التمرير."</string>
@@ -105,18 +105,18 @@
     <string name="kg_wrong_pin" msgid="1131306510833563801">"رقم تعريف شخصي خاطئ"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"حاول مرة أخرى خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"ارسم نقشك"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"أدخل رقم التعريف الشخصي لبطاقة SIM"</string>
-    <string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رقم التعريف الشخصي"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"أدخل رمز PIN لبطاقة SIM"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رمز PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"أدخل كلمة المرور"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"بطاقة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رقم التعريف الشخصي المراد"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رقم التعريف الشخصي المراد"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رمز PIN المراد"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رمز PIN المراد"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
-    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رقم التعريف الشخصي غير صحيح."</string>
-    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رقم التعريف الشخصي المكون من 4 إلى 8 أرقام."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رمز PIN غير صحيح."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رمز PIN المكون من 4 إلى 8 أرقام."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"يجب أن يتضمن رمز PUK‏ 8 أرقام أو أكثر."</string>
     <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل بطاقة SIM نهائيًا."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رقم التعريف الشخصي"</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رمز PIN"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"لإلغاء التأمين، سجّل الدخول بحسابك في Google."</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"اسم المستخدم (البريد إلكتروني)"</string>
@@ -125,7 +125,7 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"اسم مستخدم غير صحيح أو كلمة مرور غير صالحة."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"هل نسيت اسم المستخدم أو كلمة المرور؟\nانتقل إلى "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"جارٍ فحص الحساب…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"لقد كتبت رقم التعريف الشخصي بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"لقد كتبت رمز PIN بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"لقد كتبت كلمة المرور بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"لقد رسمت نقش إلغاء التأمين بطريقة غير صحيحة <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"لقد حاولت إلغاء تأمين الجهاز اللوحي بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستتم إعادة تعيين الجهاز اللوحي على الإعدادات الافتراضية للمصنع وسيتم فقد جميع بيانات المستخدم."</string>
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index f8a1362..ea5ef27 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -66,4 +66,7 @@
     <dimen name="widget_label_font_size">16dp</dimen>
     <dimen name="widget_big_font_size">141dp</dimen>
 
+    <!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text.
+         Should be 0 on devices with plenty of room (e.g. tablets) -->
+    <dimen name="eca_overlap">0dip</dimen>
 </resources>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index a1ad120..71e9924 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -150,6 +150,10 @@
     security mode. -->
     <dimen name="kg_small_widget_height">160dp</dimen>
 
+    <!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text.
+         Should be 0 on devices with plenty of room (e.g. tablets) -->
+    <dimen name="eca_overlap">-10dip</dimen>
+
     <!-- Default clock parameters -->
     <dimen name="bottom_text_spacing_digital">-8dp</dimen>
     <dimen name="label_font_size">14dp</dimen>
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index abc4483..4738049 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -24,12 +24,12 @@
 
     <!-- Instructions telling the user to enter their SIM PUK to unlock the keyguard.
          Displayed in one line in a large font.  -->
-    <string name="keyguard_password_enter_puk_code">Type PUK and new PIN code</string>
+    <string name="keyguard_password_enter_puk_code">Type SIM PUK and new PIN code</string>
 
     <!-- Prompt to enter SIM PUK in Edit Text Box in unlock screen -->
-    <string name="keyguard_password_enter_puk_prompt">PUK code</string>
+    <string name="keyguard_password_enter_puk_prompt">SIM PUK code</string>
     <!-- Prompt to enter New SIM PIN in Edit Text Box in unlock screen -->
-    <string name="keyguard_password_enter_pin_prompt">New PIN code</string>
+    <string name="keyguard_password_enter_pin_prompt">New SIM PIN code</string>
 
     <!-- Displayed as hint in passwordEntry EditText on PasswordUnlockScreen [CHAR LIMIT=30]-->
     <string name="keyguard_password_entry_touch_hint"><font size="17">Touch to type password</font></string>
@@ -249,8 +249,6 @@
     <string name="kg_enter_confirm_pin_hint">Confirm desired PIN code</string>
     <!-- Message shown in dialog while the device is unlocking the SIM card -->
     <string name="kg_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
-    <!-- Message shown when the user enters the wrong PIN code -->
-    <string name="kg_password_wrong_pin_code">Incorrect PIN code.</string>
     <!-- Message shown when the user enters an invalid SIM pin password in PUK screen -->
     <string name="kg_invalid_sim_pin_hint">Type a PIN that is 4 to 8 numbers.</string>
     <!-- Message shown when the user enters an invalid PUK code in the PUK screen -->
@@ -333,6 +331,34 @@
     <!-- The delete-widget drop target button text -->
     <string name="kg_reordering_delete_drop_target_text">Remove</string>
 
+    <!-- Instructions telling the user that they entered the wrong SIM PIN for the last time.
+         Displayed in a dialog box.  -->
+    <string name="kg_password_wrong_pin_code_pukked">Incorrect SIM PIN code you must now contact your carrier to unlock your device.</string>
+    <!-- Instructions telling the user that they entered the wrong SIM PIN while trying
+         to unlock the keyguard.  Displayed in a dialog box.  -->
+    <plurals name="kg_password_wrong_pin_code">
+        <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item>
+        <item quantity="other">Incorrect SIM PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item>
+    </plurals>
+
+    <!-- Instructions telling the user that they have exhausted SIM PUK retries and the SIM is now unusable.
+         Displayed in a dialog box.  -->
+    <string name="kg_password_wrong_puk_code_dead">SIM is unusable. Contact your carrier.</string>
+    <!-- Instructions telling the user that they entered the wrong puk while trying
+         to unlock the keyguard.  Displayed in a dialog box.  -->
+    <plurals name="kg_password_wrong_puk_code">
+        <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable.</item>
+        <item quantity="other">Incorrect SIM PUK code, you have <xliff:g id="number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
+    </plurals>
+    <!-- Instructions telling the user that the operation to unlock the keyguard
+         with SIM PIN failed. Displayed in one line in a large font.  -->
+    <string name="kg_password_pin_failed">SIM PIN operation failed!</string>
+    <!-- Instructions telling the user that the operation to unlock the keyguard
+         with PUK failed. Displayed in one line in a large font.  -->
+    <string name="kg_password_puk_failed">SIM PUK operation failed!</string>
+    <!-- Notification telling the user that the PIN1 they entered is valid -->
+    <string name="kg_pin_accepted">Code Accepted!</string>
+
     <!-- Transport control strings -->
     <!-- Shown on transport control of lockscreen. Pressing button goes to previous track. -->
     <string name="keyguard_transport_prev_description">Previous track button</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index e94cf18..fdc06a6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -16,6 +16,10 @@
 
 package com.android.keyguard;
 
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
+
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -51,9 +55,6 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.RemoteViews.OnClickHandler;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
 
 import java.io.File;
 import java.lang.ref.WeakReference;
@@ -279,7 +280,7 @@
             if (newState != mTransportState) {
                 mTransportState = newState;
                 if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
-                KeyguardHostView.this.postShowAppropriateWidgetPage();
+                KeyguardHostView.this.post(mSwitchPageRunnable);
             }
         }
         @Override
@@ -291,7 +292,7 @@
                 if (newState != mTransportState) {
                     mTransportState = newState;
                     if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
-                    KeyguardHostView.this.postShowAppropriateWidgetPage();
+                    KeyguardHostView.this.post(mSwitchPageRunnable);
                 }
             }
         }
@@ -495,7 +496,6 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        removeCallbacks(mSwitchPageRunnable);
         mAppWidgetHost.stopListening();
         KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
     }
@@ -1438,7 +1438,7 @@
         mAppWidgetToShow = ss.appWidgetToShow;
         setInsets(ss.insets);
         if (DEBUG) Log.d(TAG, "onRestoreInstanceState, transport=" + mTransportState);
-        postShowAppropriateWidgetPage();
+        post(mSwitchPageRunnable);
     }
 
     @Override
@@ -1471,22 +1471,13 @@
         }
     }
 
-    void showAppropriateWidgetPage() {
+    private void showAppropriateWidgetPage() {
         int state = mTransportState;
         ensureTransportPresentOrRemoved(state);
-        if (mAppWidgetContainer.isLayoutRequested()) {
-            postShowAppropriateWidgetPage();
-            return;
-        }
         int pageToShow = getAppropriateWidgetPage(state);
         mAppWidgetContainer.setCurrentPage(pageToShow);
     }
 
-    void postShowAppropriateWidgetPage() {
-        removeCallbacks(mSwitchPageRunnable);
-        post(mSwitchPageRunnable);
-    }
-
     /**
      * Examines the current state and adds the transport to the widget pager when the state changes.
      *
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
index d7c5fe2..36b2446 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
@@ -141,6 +141,10 @@
             checkPermission();
             mKeyguardViewMediator.launchCamera();
         }
+        public void onBootCompleted() {
+            checkPermission();
+            mKeyguardViewMediator.onBootCompleted();
+        }
     };
 
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index 5059407..e39622a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -17,11 +17,16 @@
 package com.android.keyguard;
 
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.PhoneConstants;
 
 import android.content.Context;
+import android.content.DialogInterface;
 import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.app.ProgressDialog;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.Editable;
@@ -30,6 +35,7 @@
 import android.text.method.DigitsKeyListener;
 import android.util.AttributeSet;
 import android.view.View;
+import android.util.Log;
 import android.view.WindowManager;
 import android.widget.TextView.OnEditorActionListener;
 
@@ -38,10 +44,14 @@
  */
 public class KeyguardSimPinView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+    private static final String LOG_TAG = "KeyguardSimPinView";
+    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
 
     private ProgressDialog mSimUnlockProgressDialog = null;
     private volatile boolean mSimCheckInProgress;
 
+    private AlertDialog mRemainingAttemptsDialog;
+
     public KeyguardSimPinView(Context context) {
         this(context, null);
     }
@@ -55,6 +65,23 @@
         mPasswordEntry.setEnabled(true);
     }
 
+    private String getPinPasswordErrorMessage(int attemptsRemaining) {
+        String displayMessage;
+
+        if (attemptsRemaining == 0) {
+            displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked);
+        } else if (attemptsRemaining > 0) {
+            displayMessage = getContext().getResources()
+                    .getQuantityString(R.plurals.kg_password_wrong_pin_code, attemptsRemaining,
+                            attemptsRemaining);
+        } else {
+            displayMessage = getContext().getString(R.string.kg_password_pin_failed);
+        }
+        if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
+                + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
+        return displayMessage;
+    }
+
     @Override
     protected boolean shouldLockout(long deadline) {
         // SIM PIN doesn't have a timed lockout
@@ -109,6 +136,8 @@
                 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
 
         mPasswordEntry.requestFocus();
+
+        mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
     }
 
     @Override
@@ -135,22 +164,22 @@
             mPin = pin;
         }
 
-        abstract void onSimCheckResponse(boolean success);
+        abstract void onSimCheckResponse(final int result, final int attemptsRemaining);
 
         @Override
         public void run() {
             try {
-                final boolean result = ITelephony.Stub.asInterface(ServiceManager
-                        .checkService("phone")).supplyPin(mPin);
+                final int[] result = ITelephony.Stub.asInterface(ServiceManager
+                        .checkService("phone")).supplyPinReportResult(mPin);
                 post(new Runnable() {
                     public void run() {
-                        onSimCheckResponse(result);
+                        onSimCheckResponse(result[0], result[1]);
                     }
                 });
             } catch (RemoteException e) {
                 post(new Runnable() {
                     public void run() {
-                        onSimCheckResponse(false);
+                        onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
                     }
                 });
             }
@@ -164,14 +193,28 @@
                     mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
             mSimUnlockProgressDialog.setIndeterminate(true);
             mSimUnlockProgressDialog.setCancelable(false);
-            if (!(mContext instanceof Activity)) {
-                mSimUnlockProgressDialog.getWindow().setType(
-                        WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-            }
+            mSimUnlockProgressDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
         }
         return mSimUnlockProgressDialog;
     }
 
+    private Dialog getSimRemainingAttemptsDialog(int remaining) {
+        String msg = getPinPasswordErrorMessage(remaining);
+        if (mRemainingAttemptsDialog == null) {
+            Builder builder = new AlertDialog.Builder(mContext);
+            builder.setMessage(msg);
+            builder.setCancelable(false);
+            builder.setNeutralButton(R.string.ok, null);
+            mRemainingAttemptsDialog = builder.create();
+            mRemainingAttemptsDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        } else {
+            mRemainingAttemptsDialog.setMessage(msg);
+        }
+        return mRemainingAttemptsDialog;
+    }
+
     @Override
     protected void verifyPasswordAndUnlock() {
         String entry = mPasswordEntry.getText().toString();
@@ -189,20 +232,34 @@
         if (!mSimCheckInProgress) {
             mSimCheckInProgress = true; // there should be only one
             new CheckSimPin(mPasswordEntry.getText().toString()) {
-                void onSimCheckResponse(final boolean success) {
+                void onSimCheckResponse(final int result, final int attemptsRemaining) {
                     post(new Runnable() {
                         public void run() {
                             if (mSimUnlockProgressDialog != null) {
                                 mSimUnlockProgressDialog.hide();
                             }
-                            if (success) {
-                                // before closing the keyguard, report back that the sim is unlocked
-                                // so it knows right away.
+                            if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
                                 KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
                                 mCallback.dismiss(true);
                             } else {
-                                mSecurityMessageDisplay.setMessage
-                                    (R.string.kg_password_wrong_pin_code, true);
+                                if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
+                                    if (attemptsRemaining <= 2) {
+                                        // this is getting critical - show dialog
+                                        getSimRemainingAttemptsDialog(attemptsRemaining).show();
+                                    } else {
+                                        // show message
+                                        mSecurityMessageDisplay.setMessage(
+                                                getPinPasswordErrorMessage(attemptsRemaining), true);
+                                    }
+                                } else {
+                                    // "PIN operation failed!" - no idea what this was and no way to
+                                    // find out. :/
+                                    mSecurityMessageDisplay.setMessage(getContext().getString(
+                                            R.string.kg_password_pin_failed), true);
+                                }
+                                if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
+                                        + " CheckSimPin.onSimCheckResponse: " + result
+                                        + " attemptsRemaining=" + attemptsRemaining);
                                 mPasswordEntry.setText("");
                             }
                             mCallback.userActivity(0);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index 2ae4cc7..31518a1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -16,10 +16,10 @@
 
 package com.android.keyguard;
 
-import com.android.internal.telephony.ITelephony;
-
 import android.content.Context;
+import android.animation.AnimatorSet.Builder;
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.ProgressDialog;
 import android.os.RemoteException;
@@ -29,21 +29,29 @@
 import android.text.TextWatcher;
 import android.text.method.DigitsKeyListener;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.PhoneConstants;
+
+
 /**
  * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
  */
 public class KeyguardSimPukView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+    private static final String LOG_TAG = "KeyguardSimPukView";
+    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
 
     private ProgressDialog mSimUnlockProgressDialog = null;
     private volatile boolean mCheckInProgress;
     private String mPukText;
     private String mPinText;
     private StateMachine mStateMachine = new StateMachine();
+    private AlertDialog mRemainingAttemptsDialog;
 
     private class StateMachine {
         final int ENTER_PUK = 0;
@@ -93,6 +101,23 @@
         }
     }
 
+    private String getPukPasswordErrorMessage(int attemptsRemaining) {
+        String displayMessage;
+
+        if (attemptsRemaining == 0) {
+            displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead);
+        } else if (attemptsRemaining > 0) {
+            displayMessage = getContext().getResources()
+                    .getQuantityString(R.plurals.kg_password_wrong_puk_code, attemptsRemaining,
+                            attemptsRemaining);
+        } else {
+            displayMessage = getContext().getString(R.string.kg_password_puk_failed);
+        }
+        if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:"
+                + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
+        return displayMessage;
+    }
+
     public KeyguardSimPukView(Context context) {
         this(context, null);
     }
@@ -190,23 +215,23 @@
             mPin = pin;
         }
 
-        abstract void onSimLockChangedResponse(boolean success);
+        abstract void onSimLockChangedResponse(final int result, final int attemptsRemaining);
 
         @Override
         public void run() {
             try {
-                final boolean result = ITelephony.Stub.asInterface(ServiceManager
-                        .checkService("phone")).supplyPuk(mPuk, mPin);
+                final int[] result = ITelephony.Stub.asInterface(ServiceManager
+                        .checkService("phone")).supplyPukReportResult(mPuk, mPin);
 
                 post(new Runnable() {
                     public void run() {
-                        onSimLockChangedResponse(result);
+                        onSimLockChangedResponse(result[0], result[1]);
                     }
                 });
             } catch (RemoteException e) {
                 post(new Runnable() {
                     public void run() {
-                        onSimLockChangedResponse(false);
+                        onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
                     }
                 });
             }
@@ -228,6 +253,22 @@
         return mSimUnlockProgressDialog;
     }
 
+    private Dialog getPukRemainingAttemptsDialog(int remaining) {
+        String msg = getPukPasswordErrorMessage(remaining);
+        if (mRemainingAttemptsDialog == null) {
+            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+            builder.setMessage(msg);
+            builder.setCancelable(false);
+            builder.setNeutralButton(R.string.ok, null);
+            mRemainingAttemptsDialog = builder.create();
+            mRemainingAttemptsDialog.getWindow().setType(
+                    WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        } else {
+            mRemainingAttemptsDialog.setMessage(msg);
+        }
+        return mRemainingAttemptsDialog;
+    }
+
     private boolean checkPuk() {
         // make sure the puk is at least 8 digits long.
         if (mPasswordEntry.getText().length() >= 8) {
@@ -257,17 +298,33 @@
         if (!mCheckInProgress) {
             mCheckInProgress = true;
             new CheckSimPuk(mPukText, mPinText) {
-                void onSimLockChangedResponse(final boolean success) {
+                void onSimLockChangedResponse(final int result, final int attemptsRemaining) {
                     post(new Runnable() {
                         public void run() {
                             if (mSimUnlockProgressDialog != null) {
                                 mSimUnlockProgressDialog.hide();
                             }
-                            if (success) {
+                            if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
+                                KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
                                 mCallback.dismiss(true);
                             } else {
+                                if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
+                                    if (attemptsRemaining <= 2) {
+                                        // this is getting critical - show dialog
+                                        getPukRemainingAttemptsDialog(attemptsRemaining).show();
+                                    } else {
+                                        // show message
+                                        mSecurityMessageDisplay.setMessage(
+                                                getPukPasswordErrorMessage(attemptsRemaining), true);
+                                    }
+                                } else {
+                                    mSecurityMessageDisplay.setMessage(getContext().getString(
+                                            R.string.kg_password_puk_failed), true);
+                                }
+                                if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
+                                        + " UpdateSim.onSimCheckResponse: "
+                                        + " attemptsRemaining=" + attemptsRemaining);
                                 mStateMachine.reset();
-                                mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk, true);
                             }
                             mCheckInProgress = false;
                         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
index a7af6a4..de26efb 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
@@ -134,6 +134,7 @@
     private final Runnable mUpdateSeekBars = new Runnable() {
         public void run() {
             if (updateSeekBars()) {
+                removeCallbacks(this);
                 postDelayed(this, 1000);
             }
         }
@@ -249,7 +250,6 @@
         }
         if (enabled) {
             mUpdateSeekBars.run();
-            postDelayed(mUpdateSeekBars, 1000);
         } else {
             removeCallbacks(mUpdateSeekBars);
         }
@@ -437,8 +437,7 @@
             setSeekBarsEnabled(false);
         }
 
-        KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(
-                mMetadata.bitmap);
+        KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(mMetadata.bitmap);
         final int flags = mTransportControlFlags;
         setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
         setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
@@ -539,7 +538,7 @@
                 imageResId = R.drawable.ic_media_pause;
                 imageDescId = R.string.keyguard_transport_pause_description;
                 if (mSeekEnabled) {
-                    postDelayed(mUpdateSeekBars, 1000);
+                    mUpdateSeekBars.run();
                 }
                 break;
 
@@ -567,6 +566,7 @@
     boolean updateSeekBars() {
         final int position = (int) mRemoteController.getEstimatedMediaPosition();
         if (position >= 0) {
+            if (DEBUG) Log.v(TAG, "Seek to " + position);
             if (!mUserSeeking) {
                 mTransientSeekBar.setProgress(position);
             }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 45cd3d4..520cea3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -635,15 +635,14 @@
      * PhoneWindowManager in this case.
      */
     protected void dispatchBootCompleted() {
-        if (!mBootCompleted) {
-            mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
-        }
+        mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
     }
 
     /**
      * Handle {@link #MSG_BOOT_COMPLETED}
      */
     protected void handleBootCompleted() {
+        if (mBootCompleted) return;
         mBootCompleted = true;
         mAudioManager = new AudioManager(mContext);
         mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
index a37a3a4..b92ae90 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
@@ -530,9 +530,6 @@
             mSystemReady = true;
             mUpdateMonitor.registerCallback(mUpdateCallback);
 
-            // Send boot completed message if it hasn't already been sent.
-            mUpdateMonitor.dispatchBootCompleted();
-
             // Suppress biometric unlock right after boot until things have settled if it is the
             // selected security method, otherwise unsuppress it.  It must be unsuppressed if it is
             // not the selected security method for the following reason:  if the user starts
@@ -1366,4 +1363,8 @@
         Message msg = mHandler.obtainMessage(LAUNCH_CAMERA);
         mHandler.sendMessage(msg);
     }
+
+    public void onBootCompleted() {
+        mUpdateMonitor.dispatchBootCompleted();
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
index e07e0d0..704af6e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
@@ -40,6 +40,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.TextClock;
+
 import com.android.internal.widget.LockPatternUtils;
 
 import java.util.ArrayList;
diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
index 2749aa6..1a61b99 100644
--- a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
@@ -15,13 +15,13 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:paddingStart="16dip"
-        android:paddingEnd="16dip"
-        android:minHeight="?android:attr/listPreferredItemHeightSmall"
-        android:orientation="horizontal"
-        android:gravity="start|center_vertical">
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:paddingStart="16dip"
+      android:paddingEnd="16dip"
+      android:minHeight="?android:attr/listPreferredItemHeightSmall"
+      android:orientation="horizontal"
+      android:gravity="start|center_vertical">
 
     <ImageView
         android:id="@+id/icon"
@@ -31,7 +31,7 @@
         android:layout_marginEnd="8dip"
         android:duplicateParentState="true"
         android:contentDescription="@null"
-        android:visibility="gone">
+        android:visibility="invisible">
     </ImageView>
 
     <LinearLayout
diff --git a/packages/PrintSpooler/res/layout/printer_list_item.xml b/packages/PrintSpooler/res/layout/printer_list_item.xml
new file mode 100644
index 0000000..47eb0b5
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/printer_list_item.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:minHeight="?android:attr/listPreferredItemHeight"
+        android:orientation="horizontal"
+        android:gravity="start|center_vertical">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="32dip"
+        android:layout_height="32dip"
+        android:layout_gravity="center_vertical"
+        android:layout_marginEnd="8dip"
+        android:duplicateParentState="true"
+        android:contentDescription="@null"
+        android:visibility="gone">
+    </ImageView>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:duplicateParentState="true">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textIsSelectable="false"
+            android:gravity="top|start"
+            android:textColor="@color/item_text_color"
+            android:duplicateParentState="true">
+        </TextView>
+
+        <TextView
+            android:id="@+id/subtitle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textIsSelectable="false"
+            android:visibility="gone"
+            android:textColor="@color/print_option_title"
+            android:duplicateParentState="true">
+        </TextView>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/select_printer_fragment.xml b/packages/PrintSpooler/res/layout/select_printer_fragment.xml
new file mode 100644
index 0000000..bbd012e
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/select_printer_fragment.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:paddingStart="@dimen/printer_list_view_padding_start"
+    android:paddingEnd="@dimen/printer_list_view_padding_end"
+    android:scrollbarStyle="outsideOverlay"
+    android:cacheColorHint="@android:color/transparent"
+    android:scrollbarAlwaysDrawVerticalTrack="true" >
+</ListView>
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index a6ad391..5ea5ed9 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -60,7 +60,7 @@
     <string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met drukker nie"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"onbekend"</string>
     <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nie beskikbaar nie"</string>
-    <string name="print_error_default_message" msgid="8568506918983980567">"Kon nie druktaak genereer nie"</string>
+    <string name="print_error_default_message" msgid="8568506918983980567">"Kon nie uitdruktaak genereer nie"</string>
   <string-array name="color_mode_labels">
     <item msgid="7602948745415174937">"Swart en wit"</item>
     <item msgid="2762241247228983754">"Kleur"</item>
diff --git a/packages/PrintSpooler/res/values-land/constants.xml b/packages/PrintSpooler/res/values-land/constants.xml
new file mode 100644
index 0000000..d68b77e
--- /dev/null
+++ b/packages/PrintSpooler/res/values-land/constants.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+    <dimen name="printer_list_view_padding_start">48dip</dimen>
+    <dimen name="printer_list_view_padding_end">48dip</dimen>
+
+</resources>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 62af20b..ec5855f 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -60,7 +60,7 @@
     <string name="no_connection_to_printer" msgid="2159246915977282728">"Nav savienojuma ar printeri"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"nezināms"</string>
     <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> — nav pieejams"</string>
-    <string name="print_error_default_message" msgid="8568506918983980567">"Nevar ģenerēt drukas darbu"</string>
+    <string name="print_error_default_message" msgid="8568506918983980567">"Nevarēja ģenerēt drukas darbu"</string>
   <string-array name="color_mode_labels">
     <item msgid="7602948745415174937">"Melnbalts"</item>
     <item msgid="2762241247228983754">"Krāsa"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 2f16a22..4b5d5c9 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -25,7 +25,7 @@
     <string name="label_color" msgid="1108690305218188969">"顏色"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="6300874667546617333">"頁數 (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
-    <string name="pages_range_example" msgid="8558694453556945172">"例如:1–5、8、11–13"</string>
+    <string name="pages_range_example" msgid="8558694453556945172">"例如:1-5,8,11-13"</string>
     <string name="print_preview" msgid="8010217796057763343">"預覽列印"</string>
     <string name="install_for_print_preview" msgid="6366303997385509332">"安裝預覽所需的 PDF 檢視器"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"列印應用程式當機了"</string>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index e5a9d5d..e9c925c 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -26,4 +26,7 @@
 
     <dimen name="print_dialog_frame_max_width_dip">400dip</dimen>
 
-</resources>
\ No newline at end of file
+    <dimen name="printer_list_view_padding_start">16dip</dimen>
+    <dimen name="printer_list_view_padding_end">16dip</dimen>
+
+</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 2997707..db3770e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -40,6 +40,7 @@
 import android.os.RemoteException;
 import android.print.ILayoutResultCallback;
 import android.print.IPrintDocumentAdapter;
+import android.print.IPrintDocumentAdapterObserver;
 import android.print.IWriteResultCallback;
 import android.print.PageRange;
 import android.print.PrintAttributes;
@@ -201,6 +202,14 @@
             throw new IllegalArgumentException("PrintDocumentAdapter cannot be null");
         }
 
+        try {
+            IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter)
+                    .setObserver(new PrintDocumentAdapterObserver(this));
+        } catch (RemoteException re) {
+            finish();
+            return;
+        }
+
         PrintAttributes attributes = printJob.getAttributes();
         if (attributes != null) {
             mCurrPrintAttributes.copyFrom(attributes);
@@ -249,27 +258,29 @@
         // We can safely do the work in here since at this point
         // the system is bound to our (spooler) process which
         // guarantees that this process will not be killed.
-        if (mController.hasStarted()) {
+        if (mController != null && mController.hasStarted()) {
             mController.finish();
         }
-        if (mEditor.isPrintConfirmed() && mController.isFinished()) {
-            mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
-                    PrintJobInfo.STATE_QUEUED, null);
+        if (mEditor != null && mEditor.isPrintConfirmed()
+                && mController != null && mController.isFinished()) {
+                mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
+                        PrintJobInfo.STATE_QUEUED, null);
         } else {
             mSpoolerProvider.getSpooler().setPrintJobState(mPrintJobId,
                     PrintJobInfo.STATE_CANCELED, null);
         }
-        mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
         if (mGeneratingPrintJobDialog != null) {
             mGeneratingPrintJobDialog.dismiss();
             mGeneratingPrintJobDialog = null;
         }
+        mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
         mSpoolerProvider.destroy();
         super.onDestroy();
     }
 
     public boolean onTouchEvent(MotionEvent event) {
-        if (!mEditor.isPrintConfirmed() && mEditor.shouldCloseOnTouch(event)) {
+        if (mController != null && mEditor != null &&
+                !mEditor.isPrintConfirmed() && mEditor.shouldCloseOnTouch(event)) {
             if (!mController.isWorking()) {
                 PrintJobConfigActivity.this.finish();
             }
@@ -287,17 +298,19 @@
     }
 
     public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
-            if (mEditor.isShwoingGeneratingPrintJobUi()) {
+        if (mController != null && mEditor != null) {
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                if (mEditor.isShwoingGeneratingPrintJobUi()) {
+                    return true;
+                }
+                if (event.isTracking() && !event.isCanceled()) {
+                    if (!mController.isWorking()) {
+                        PrintJobConfigActivity.this.finish();
+                    }
+                }
+                mEditor.cancel();
                 return true;
             }
-            if (event.isTracking() && !event.isCanceled()) {
-                if (!mController.isWorking()) {
-                    PrintJobConfigActivity.this.finish();
-                }
-            }
-            mEditor.cancel();
-            return true;
         }
         return super.onKeyUp(keyCode, event);
     }
@@ -608,7 +621,7 @@
                         .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
                 Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
                 intent.setType("application/pdf");
-                intent.putExtra(Intent.EXTRA_TITLE, printJob.getLabel());
+                intent.putExtra(Intent.EXTRA_TITLE, mDocument.info.getName());
                 intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, mCallingPackageName);
                 startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
             } else {
@@ -2303,8 +2316,6 @@
                             R.layout.printer_dropdown_item, parent, false);
                 }
 
-                convertView.getLayoutParams().width = mDestinationSpinner.getWidth();
-
                 CharSequence title = null;
                 CharSequence subtitle = null;
                 Drawable icon = null;
@@ -2353,7 +2364,7 @@
                     iconView.setImageDrawable(icon);
                     iconView.setVisibility(View.VISIBLE);
                 } else {
-                    iconView.setVisibility(View.GONE);
+                    iconView.setVisibility(View.INVISIBLE);
                 }
 
                 return convertView;
@@ -2703,4 +2714,32 @@
             /* do noting - we are in the same process */
         }
     }
+
+    private static final class PrintDocumentAdapterObserver
+            extends IPrintDocumentAdapterObserver.Stub {
+        private final WeakReference<PrintJobConfigActivity> mWeakActvity;
+
+        public PrintDocumentAdapterObserver(PrintJobConfigActivity activity) {
+            mWeakActvity = new WeakReference<PrintJobConfigActivity>(activity);
+        }
+
+        @Override
+        public void onDestroy() {
+            final PrintJobConfigActivity activity = mWeakActvity.get();
+            if (activity != null) {
+                activity.mController.mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (activity.mController != null) {
+                            activity.mController.cancel();
+                        }
+                        if (activity.mEditor != null) {
+                            activity.mEditor.cancel();
+                        }
+                        activity.finish();
+                    }
+                });
+            }
+        }
+    }
 }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
index be94ba4..204c152 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -22,7 +22,6 @@
 import android.app.DialogFragment;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
-import android.app.ListFragment;
 import android.app.LoaderManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -47,12 +46,14 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.BaseAdapter;
 import android.widget.Filter;
@@ -68,7 +69,7 @@
 /**
  * This is a fragment for selecting a printer.
  */
-public final class SelectPrinterFragment extends ListFragment {
+public final class SelectPrinterFragment extends Fragment {
 
     private static final String LOG_TAG = "SelectPrinterFragment";
 
@@ -83,6 +84,8 @@
     private final ArrayList<PrintServiceInfo> mAddPrinterServices =
             new ArrayList<PrintServiceInfo>();
 
+    private ListView mListView;
+
     private AnnounceFilterResult mAnnounceFilterResult;
 
     public static interface OnPrinterSelectedListener {
@@ -97,8 +100,12 @@
     }
 
     @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        View content = inflater.inflate(R.layout.select_printer_fragment, container, false);
+
+        // Hook up the list view.
+        mListView = (ListView) content.findViewById(android.R.id.list);
         final DestinationAdapter adapter = new DestinationAdapter();
         adapter.registerDataSetObserver(new DataSetObserver() {
             @Override
@@ -115,7 +122,23 @@
                 }
             }
         });
-        setListAdapter(adapter);
+        mListView.setAdapter(adapter);
+
+        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position);
+                Activity activity = getActivity();
+                if (activity instanceof OnPrinterSelectedListener) {
+                    ((OnPrinterSelectedListener) activity).onPrinterSelected(printer.getId());
+                } else {
+                    throw new IllegalStateException("the host activity must implement"
+                            + " OnPrinterSelectedListener");
+                }
+            }
+        });
+
+        return content;
     }
 
     @Override
@@ -133,7 +156,7 @@
 
             @Override
             public boolean onQueryTextChange(String searchString) {
-                ((DestinationAdapter) getListAdapter()).getFilter().filter(searchString);
+                ((DestinationAdapter) mListView.getAdapter()).getFilter().filter(searchString);
                 return true;
             }
         });
@@ -177,18 +200,6 @@
     }
 
     @Override
-    public void onListItemClick(ListView list, View view, int position, long id) {
-        PrinterInfo printer = (PrinterInfo) list.getAdapter().getItem(position);
-        Activity activity = getActivity();
-        if (activity instanceof OnPrinterSelectedListener) {
-            ((OnPrinterSelectedListener) activity).onPrinterSelected(printer.getId());
-        } else {
-            throw new IllegalStateException("the host activity must implement"
-                    + " OnPrinterSelectedListener");
-        }
-    }
-
-    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (item.getItemId() == R.id.action_add_printer) {
             showAddPrinterSelectionDialog();
@@ -260,9 +271,9 @@
     }
 
     public void updateEmptyView(DestinationAdapter adapter) {
-        if (getListView().getEmptyView() == null) {
+        if (mListView.getEmptyView() == null) {
             View emptyView = getActivity().findViewById(R.id.empty_print_state);
-            getListView().setEmptyView(emptyView);
+            mListView.setEmptyView(emptyView);
         }
         TextView titleView = (TextView) getActivity().findViewById(R.id.title);
         View progressBar = getActivity().findViewById(R.id.progress_bar);
@@ -450,7 +461,7 @@
         public View getView(int position, View convertView, ViewGroup parent) {
             if (convertView == null) {
                 convertView = getActivity().getLayoutInflater().inflate(
-                        R.layout.printer_dropdown_item, parent, false);
+                        R.layout.printer_list_item, parent, false);
             }
 
             convertView.setEnabled(isEnabled(position));
@@ -539,16 +550,16 @@
 
         public void post() {
             remove();
-            getListView().postDelayed(this, SEARCH_RESULT_ANNOUNCEMENT_DELAY);
+            mListView.postDelayed(this, SEARCH_RESULT_ANNOUNCEMENT_DELAY);
         }
 
         public void remove() {
-            getListView().removeCallbacks(this);
+            mListView.removeCallbacks(this);
         }
 
         @Override
         public void run() {
-            final int count = getListView().getAdapter().getCount();
+            final int count = mListView.getAdapter().getCount();
             final String text;
             if (count <= 0) {
                 text = getString(R.string.print_no_printers);
@@ -556,7 +567,7 @@
                 text = getActivity().getResources().getQuantityString(
                     R.plurals.print_search_result_count_utterance, count, count);
             }
-            getListView().announceForAccessibility(text);
+            mListView.announceForAccessibility(text);
         }
     }
 }
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 3374d37..53dcb5a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Battery <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Vliegtuigmodus <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Wekker gestel vir <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-data gedeaktiveer"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data gedeaktiveer"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 164ec7d..00f261c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ባትሪ <xliff:g id="STATE">%s</xliff:g>።"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"የአውሮፕላን ሁነታ <xliff:g id="STATE">%s</xliff:g>።"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ብሉቱዝ <xliff:g id="STATE">%s</xliff:g>።"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ማንቂያ ለ<xliff:g id="TIME">%s</xliff:g> ተዋቅሯል።"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ውሂብ ቦዝኗል"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G ውሂብ ቦዝኗል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2ab8cbe..b641b94 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"البطارية <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"وضع الطائرة <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"البلوتوث <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"تم ضبط المنبه على <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"تم تعطيل بيانات شبكات الجيل الثاني والجيل الثالث"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"تم تعطيل بيانات شبكة الجيل الرابع"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index bb8e1d2..356e7df 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -157,6 +157,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Акумулятар: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Рэжым палёту: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Наладжаны будзiльнiк: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Дадзеныя 2G-3G адключаныя"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Дадзеныя 4G адключаныя"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index b951aa8..ecc0901 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батерия: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Самолетен режим: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Будилникът е навит за <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G данните са деактивирани"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G данните са деактивирани"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 9d537c5..ceffdd5 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode d\'avió <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma establerta a les <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dades 2G-3G desactivades"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dades 4G desactivades"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e975979..37df24b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterie: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Režim V letadle: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Budík je nastaven na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datové přenosy 2G a 3G jsou zakázány"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datové přenosy 4G jsou zakázány"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 25c5baa..32c995f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteri <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flytilstand <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmen er indstillet til <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-data er deaktiveret"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-data er deaktiveret"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index cc31df4..4b32cc5 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akku: <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flugmodus: <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Wecker gestellt für <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-/3G-Daten deaktiviert"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-Daten deaktiviert"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 37fa359..4c9b4843 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Μπαταρία <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Λειτουργία πτήσης <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Το ξυπνητήρι έχει οριστεί στις <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Τα δεδομένα 2G-3G απενεργοποιήθηκαν"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Τα δεδομένα 4G απενεργοποιήθηκαν"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index fb32af1..ac4c372 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Battery <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Aeroplane Mode <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set for <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G data disabled"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data disabled"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index fb32af1..ac4c372 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Battery <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Aeroplane Mode <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set for <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G data disabled"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data disabled"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 54ad455..cd149df 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avión <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos de 2G-3G inhabilitados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datos de 4G inhabilitados"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 7dcb079..ee612b8 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avión <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"La alarma sonará a la(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos 2G-3G inhabilitados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datos 4G inhabilitados"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index d485a55..d962c65 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Aku: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lennukirežiim: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Määratud äratus: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G andmeside keelatud"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G andmeside keelatud"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index d9f193f..b57982a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"باتری <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"حالت هواپیما <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"بلوتوث <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"هشدار برای <xliff:g id="TIME">%s</xliff:g> تنظیم شد."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"داده 2G-3G غیرفعال شد"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"داده 4G غیر فعال شد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4607365..cbdce43 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akku: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lentokonetila <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Hälytys asetettu, aika: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-tiedonsiirto pois käytöstä"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-tiedonsiirto pois käytöstä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8b49129..36cbf14 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batterie : <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode Avion : <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G  désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 45e407d2..f948b9c 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batterie : <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode Avion : <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 8ec75fc..2a6f545 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"बैटरी <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"हवाई जहाज़ मोड <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"<xliff:g id="TIME">%s</xliff:g> के लिए अलार्म सेट किया गया."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G डेटा अक्षम"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G डेटा अक्षम"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 305ebcf..7bf74b3 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterija – <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Način rada u zrakoplovu <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Vrijeme alarma: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Onemogućeni su 2G-3G podaci"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Onemogućeni su 4G podaci"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2127b7e..89517e2 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akkumulátor <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Repülős üzemmód <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Ébresztés időpontja: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G adatforgalom letiltva"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G adatforgalom letiltva"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 7b38bf4..3579ecb 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Մարտկոցը <xliff:g id="STATE">%s</xliff:g> է:"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Ինքնաթիռային ռեժիմը <xliff:g id="STATE">%s</xliff:g> է:"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth-ը <xliff:g id="STATE">%s</xliff:g> է:"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Զարթուցիչը դրված է <xliff:g id="TIME">%s</xliff:g>-ին:"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G տվյալները անջատված են"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G տվյալները անջատված են"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 2b23405..98f05cd 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterai <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode Pesawat <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm disetel ke <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data 2G-3G dinonaktifkan"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data 4G dinonaktifkan"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index d833ec1a..349b07e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteria: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modalità aereo: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Allarme impostato per: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dati 2G-3G disattivati"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dati 4G disattivati"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 7dd99b6..bd13858 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"סוללה <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"מצב טיסה <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth ‏<xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ההתראה נקבעה ל-<xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"נתוני 2G-3G מושבתים"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"נתוני 4G מושבתים"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 725d599..c52c096 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池<xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"機内モード<xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"アラームは<xliff:g id="TIME">%s</xliff:g>に設定されています。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G~3Gデータが無効になりました"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4Gデータが無効になりました"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index a3d98b7..af576ab 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ელემენტი: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"თვითმფრინავის რეჟიმი <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"მაღვიძარა დაყენებულია: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ინტერნეტი გაითიშა."</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G მონაცემები გათიშულია"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 02e641c..ea6990b 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ថ្ម <xliff:g id="STATE">%s</xliff:g> ។"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"របៀបពេល​ជិះ​យន្ត​ហោះ <xliff:g id="STATE">%s</xliff:g> ។"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ប៊្លូធូស <xliff:g id="STATE">%s</xliff:g> ។"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"កំណត់​សំឡេង​រោទ៍​សម្រាប់ <xliff:g id="TIME">%s</xliff:g> ។"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"បាន​បិទ​ទិន្នន័យ 2G-3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"បាន​បិទ​ទិន្នន័យ 4G"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 82f9b89..2e4df41 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"배터리 <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"비행기 모드가 <xliff:g id="STATE">%s</xliff:g> 상태입니다."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"블루투스 <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"알람이 <xliff:g id="TIME">%s</xliff:g>(으)로 설정되었습니다."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G 데이터 사용중지됨"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G 데이터 사용중지됨"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index ec14830..34ba1a8 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ແບັດເຕີຣີ <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"ໂໝດໃນຍົນ <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ຕັ້ງໂມງປຸກ <xliff:g id="TIME">%s</xliff:g> ແລ້ວ."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"ອິນເຕີເນັດ 2G​, 3G ຖືກປິດແລ້ວ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"ການນຳໃຊ້ຂໍ້ມູນ 4G ຖືກປິດແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index abb2240..620e496 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akumuliatorius <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lėktuvo režimas <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"„Bluetooth“ <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Signalas nustatytas <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G duomenys neleidžiami"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G duomenys neleidžiami"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0d01924..b6ea438 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Akumulatora statuss: <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Lidojuma režīma statuss: <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth statuss: <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Signāls ir iestatīts uz: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G dati atspējoti"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G dati atspējoti"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 0e6c032..8521caf 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батерей <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Нислэгийн горим <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Блютүүт <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Сэрүүлгийг <xliff:g id="TIME">%s</xliff:g>-д тохируулсан."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G дата идэвхгүй болов"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G дата идэвхгүй байна"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 7aa20fc..269f35c 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateri <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mod Pesawat <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Penggera ditetapkan pada <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data 2G-3G dilumpuhkan"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data 4G dilumpuhkan"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 56db18f..9ef5eb2 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteri – <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flymodus – <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth – <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmen ble stilt for <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G-data er deaktivert"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-data er deaktivert"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index deda030..3516049 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Accu: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Vliegmodus: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm is ingesteld op <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-/3G-gegevens uitgeschakeld"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G-gegevens uitgeschakeld"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 41dfd42..d0ab172 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Tryb samolotowy: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm ustawiony na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Wyłączono transmisję danych 2G/3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Wyłączono transmisję danych 4G"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b1f599b..6110e37 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo de Avião <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Os dados 2G-3G estão desativados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Os dados 4G estão desativados"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index ae9ea1e..bd0cb7c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Bateria <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avião <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dados 2G e 3G desativados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dados 4G desativados"</string>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 287b382..9e1c9b8 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -276,6 +276,8 @@
     <skip />
     <!-- no translation found for accessibility_quick_settings_bluetooth (5749054971341882340) -->
     <skip />
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <!-- no translation found for accessibility_quick_settings_alarm (3959908972897295660) -->
     <skip />
     <!-- no translation found for data_usage_disabled_dialog_3g_title (5257833881698644687) -->
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index f57c3b5..6068662 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterie <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mod Avion <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmă setată pentru <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datele 2G-3G au fost dezactivate"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datele 4G au fost dezactivate"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index f7bb4d3..85f5064 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батарея: <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Режим полета <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Будильник установлен на <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Передача данных по каналам 2G и 3G отключена"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Передача данных по каналу 4G отключена"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 4fdb8078..0e71e38 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batéria: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Režim V lietadle: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Budík nastavený na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dátové prenosy 2G a 3G sú zakázané"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dátové prenosy 4G sú zakázané"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 27369ea..b85a5dd 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Baterija: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Letalski način: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm je nastavljen na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Podatki 2G-3G so onemogočeni"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Podatki 4G so onemogočeni"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 7c182a20..e7f191a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батерија: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Режим рада у авиону: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Аларм је подешен за <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G–3G подаци су онемогућени"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G подаци су онемогућени"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 99d19f0..ce46ccc 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batteri <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Flygplansläge <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmet ringer <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data via 2G-3G har inaktiverats"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data via 4G har inaktiverats"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7c7f661..36eeded 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -151,6 +151,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Betri <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Hali ya Ndege <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Kengele imewekwa <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data ya 2G-3G imelemazwa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data ya 4G imelemazwa"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 07bca1a..d5e799d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"แบตเตอรี่ <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"โหมดใช้งานบนเครื่องบิน <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"บลูทูธ <xliff:g id="STATE">%s</xliff:g>"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ตั้งเวลาปลุกไว้ที่ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"ปิดใช้งานข้อมูล 2G-3G แล้ว"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"ปิดใช้งานข้อมูล 4G แล้ว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e163333..62b11fb 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"<xliff:g id="STATE">%s</xliff:g> ng baterya."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"<xliff:g id="STATE">%s</xliff:g> ng Airplane Mode."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"<xliff:g id="STATE">%s</xliff:g> ng Bluetooth."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set para sa <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Di pinapagana ang 2G-3G na data"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Hindi pinapagana ang 4G na data"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 6fcde0c..7002fde 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Pil <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Uçak Modu <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm saati: <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G verileri devre dışı bırakıldı"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G verileri devre dışı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 9567c03..142aa8c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Акумулятор: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Режим польоту: <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Сигнал установлено на <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Дані 2G–3G вимкнено"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Дані 4G вимкнено"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 6e68c63..56b513d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Pin <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Chế độ trên máy bay <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Báo thức được đặt cho <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Đã tắt dữ liệu 2G-3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Đã tắt dữ liệu 4G"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 39d73c3..e029756 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"电池电量:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"飞行模式:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"蓝牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"闹钟已设置为:<xliff:g id="TIME">%s</xliff:g>。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G 数据网络已停用"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G 数据网络已停用"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d83455c..5b2bfb00 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池電量:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"飛航模式:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"藍牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"鬧鐘已設定為:<xliff:g id="TIME">%s</xliff:g>。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"已停用 2G-3G 數據"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"已停用 4G 數據"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 6085c34..407c8af 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -155,6 +155,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池電量:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"飛航模式:<xliff:g id="STATE">%s</xliff:g>。"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"藍牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"鬧鐘已設定為:<xliff:g id="TIME">%s</xliff:g>。"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"已停用 2G-3G 數據"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"已停用 4G 數據"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 14d3091..dc18a90 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -153,6 +153,8 @@
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Ibhethri <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Imodi yendiza <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"I-Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+    <!-- no translation found for accessibility_quick_settings_location (4577282329866813100) -->
+    <skip />
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"I-alamu isethiwe ngo-<xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"idatha ye-2G-3G ivimbelwe"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Idatha ye-4G ivimbelwe"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 58865ab..e6fcdff 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -382,6 +382,8 @@
     <string name="accessibility_quick_settings_airplane">Airplane Mode <xliff:g id="state" example="Off">%s</xliff:g>.</string>
     <!-- Content description of the bluetooth tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_bluetooth">Bluetooth <xliff:g id="state" example="Off">%s</xliff:g>.</string>
+    <!-- Content description of the location tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_location">Location <xliff:g id="state" example="Off">%s</xliff:g>.</string>
     <!-- Content description of the alarm tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_alarm">Alarm set for <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
index 90de65e..6fce732 100644
--- a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
@@ -17,6 +17,7 @@
 package com.android.systemui;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
@@ -166,15 +167,19 @@
         if (mCellSize < 512) { // assuming 512x512 images
             opts.inSampleSize = 2;
         }
+        opts.inMutable = true;
+        Bitmap loaded = null;
         for (int[] list : new int[][] { PASTRIES, RARE_PASTRIES, XRARE_PASTRIES, XXRARE_PASTRIES }) {
             for (int resid : list) {
-                final BitmapDrawable d = new BitmapDrawable(res,
-                        convertToAlphaMask(BitmapFactory.decodeResource(res, resid, opts)));
+                opts.inBitmap = loaded;
+                loaded = BitmapFactory.decodeResource(res, resid, opts);
+                final BitmapDrawable d = new BitmapDrawable(res, convertToAlphaMask(loaded));
                 d.setColorFilter(new ColorMatrixColorFilter(ALPHA_MASK));
                 d.setBounds(0, 0, mCellSize, mCellSize);
                 mDrawables.append(resid, d);
             }
         }
+        loaded = null;
         if (DEBUG) setWillNotDraw(false);
     }
 
@@ -304,8 +309,6 @@
                 v.getOverlay().add(d);
             }
 
-            v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
             lp.width = lp.height = mCellSize;
             addView(v, lp);
             place(v, pt, false);
@@ -314,7 +317,7 @@
                 v.setScaleX(0.5f * s);
                 v.setScaleY(0.5f * s);
                 v.setAlpha(0f);
-                v.animate().scaleX(s).scaleY(s).alpha(1f).setDuration(animationLen);
+                v.animate().withLayer().scaleX(s).scaleY(s).alpha(1f).setDuration(animationLen);
             }
         }
     }
@@ -323,6 +326,21 @@
         place(v, new Point(irand(0, mColumns), irand(0, mRows)), animate);
     }
 
+    // we don't have .withLayer() on general Animators
+    private final Animator.AnimatorListener makeHardwareLayerListener(final View v) {
+        return new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animator) {
+                v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                v.buildLayer();
+            }
+            @Override
+            public void onAnimationEnd(Animator animator) {
+                v.setLayerType(View.LAYER_TYPE_NONE, null);
+            }
+        };
+    }
+
     private final HashSet<View> tmpSet = new HashSet<View>();
     public synchronized void place(View v, Point pt, boolean animate) {
         final int i = pt.x;
@@ -370,7 +388,8 @@
             if (squatter != v) {
                 squatter.setTag(TAG_POS, null);
                 if (animate) {
-                    squatter.animate().scaleX(0.5f).scaleY(0.5f).alpha(0)
+                    squatter.animate().withLayer()
+                            .scaleX(0.5f).scaleY(0.5f).alpha(0)
                             .setDuration(DURATION)
                             .setInterpolator(new AccelerateInterpolator())
                             .setListener(new Animator.AnimatorListener() {
@@ -397,6 +416,7 @@
 
         if (animate) {
             v.bringToFront();
+
             AnimatorSet set1 = new AnimatorSet();
             set1.playTogether(
                     ObjectAnimator.ofFloat(v, View.SCALE_X, (float) scale),
@@ -404,7 +424,6 @@
             );
             set1.setInterpolator(new AnticipateOvershootInterpolator());
             set1.setDuration(DURATION);
-            set1.start();
 
             AnimatorSet set2 = new AnimatorSet();
             set2.playTogether(
@@ -414,6 +433,10 @@
             );
             set2.setInterpolator(new DecelerateInterpolator());
             set2.setDuration(DURATION);
+
+            set1.addListener(makeHardwareLayerListener(v));
+
+            set1.start();
             set2.start();
         } else {
             v.setX(i * mCellSize + (scale-1) * mCellSize /2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 1c8702a..8ad538b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -16,16 +16,20 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.animation.ArgbEvaluator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.animation.TimeInterpolator;
 import android.app.ActivityManager;
+import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.TransitionDrawable;
+import android.os.SystemClock;
 import android.util.Log;
 import android.view.View;
+import android.view.animation.LinearInterpolator;
 
 import com.android.systemui.R;
 
@@ -45,43 +49,16 @@
     private final String mTag;
     private final View mView;
     private final boolean mSupportsTransitions = ActivityManager.isHighEndGfx();
-
-    private final int mOpaque;
-    private final int mSemiTransparent;
+    private final BarBackgroundDrawable mBarBackground;
 
     private int mMode;
-    private ValueAnimator mColorDrawableAnimator;
-    private boolean mColorDrawableShowing;
-
-    private final ColorDrawable mColorDrawable;
-    private final TransitionDrawable mTransitionDrawable;
-    private final AnimatorUpdateListener mAnimatorListener = new AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animator) {
-            mColorDrawable.setColor((Integer) animator.getAnimatedValue());
-        }
-    };
 
     public BarTransitions(View view, int gradientResourceId) {
         mTag = "BarTransitions." + view.getClass().getSimpleName();
         mView = view;
-        final Resources res = mView.getContext().getResources();
-
-        if (DEBUG_COLORS) {
-            mOpaque = 0xff0000ff;
-            mSemiTransparent = 0x7f0000ff;
-        } else {
-            mOpaque = res.getColor(R.color.system_bar_background_opaque);
-            mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent);
-        }
-
-        mColorDrawable = new ColorDrawable(mOpaque);
-        mTransitionDrawable = new TransitionDrawable(
-                new Drawable[] { res.getDrawable(gradientResourceId), mColorDrawable });
-        mTransitionDrawable.setCrossFadeEnabled(true);
-        mTransitionDrawable.resetTransition();
+        mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
         if (mSupportsTransitions) {
-            mView.setBackground(mTransitionDrawable);
+            mView.setBackground(mBarBackground);
         }
     }
 
@@ -100,58 +77,14 @@
         }
     }
 
-    private Integer getBackgroundColor(int mode) {
-        if (mode == MODE_SEMI_TRANSPARENT) return mSemiTransparent;
-        if (mode == MODE_OPAQUE) return mOpaque;
-        if (mode == MODE_LIGHTS_OUT) return mOpaque;
-        return null;
-    }
-
     protected void onTransition(int oldMode, int newMode, boolean animate) {
         applyModeBackground(oldMode, newMode, animate);
     }
 
     protected void applyModeBackground(int oldMode, int newMode, boolean animate) {
-        if (DEBUG) Log.d(mTag, String.format("applyModeBackground %s animate=%s",
-                modeToString(newMode), animate));
-        cancelColorAnimation();
-        Integer oldColor = getBackgroundColor(oldMode);
-        Integer newColor = getBackgroundColor(newMode);
-        if (newColor != null) {
-            if (animate && oldColor != null && !oldColor.equals(newColor)) {
-                startColorAnimation(oldColor, newColor);
-            } else if (!newColor.equals(mColorDrawable.getColor())) {
-                if (DEBUG) Log.d(mTag, String.format("setColor = %08x", newColor));
-                mColorDrawable.setColor(newColor);
-            }
-        }
-        if (newColor == null && mColorDrawableShowing) {
-            if (DEBUG) Log.d(mTag, "Hide color layer");
-            if (animate) {
-                mTransitionDrawable.reverseTransition(BACKGROUND_DURATION);
-            } else {
-                mTransitionDrawable.resetTransition();
-            }
-            mColorDrawableShowing = false;
-        } else if (newColor != null && !mColorDrawableShowing) {
-            if (DEBUG) Log.d(mTag, "Show color layer");
-            mTransitionDrawable.startTransition(animate ? BACKGROUND_DURATION : 0);
-            mColorDrawableShowing = true;
-        }
-    }
-
-    private void startColorAnimation(int from, int to) {
-        if (DEBUG) Log.d(mTag, String.format("startColorAnimation %08x -> %08x", from, to));
-        mColorDrawableAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
-        mColorDrawableAnimator.addUpdateListener(mAnimatorListener);
-        mColorDrawableAnimator.start();
-    }
-
-    private void cancelColorAnimation() {
-        if (mColorDrawableAnimator != null && mColorDrawableAnimator.isStarted()) {
-            mColorDrawableAnimator.cancel();
-            mColorDrawableAnimator = null;
-        }
+        if (DEBUG) Log.d(mTag, String.format("applyModeBackground oldMode=%s newMode=%s animate=%s",
+                modeToString(oldMode), modeToString(newMode), animate));
+        mBarBackground.applyModeBackground(oldMode, newMode, animate);
     }
 
     public static String modeToString(int mode) {
@@ -161,4 +94,123 @@
         if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT";
         throw new IllegalArgumentException("Unknown mode " + mode);
     }
+
+    public void finishAnimations() {
+        mBarBackground.finishAnimation();
+    }
+
+    private static class BarBackgroundDrawable extends Drawable {
+        private final int mOpaque;
+        private final int mSemiTransparent;
+        private final Drawable mGradient;
+        private final TimeInterpolator mInterpolator;
+
+        private int mMode = -1;
+        private boolean mAnimating;
+        private long mStartTime;
+        private long mEndTime;
+
+        private int mGradientAlpha;
+        private int mColor;
+
+        private int mGradientAlphaStart;
+        private int mColorStart;
+
+        public BarBackgroundDrawable(Context context, int gradientResourceId) {
+            final Resources res = context.getResources();
+            if (DEBUG_COLORS) {
+                mOpaque = 0xff0000ff;
+                mSemiTransparent = 0x7f0000ff;
+            } else {
+                mOpaque = res.getColor(R.color.system_bar_background_opaque);
+                mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent);
+            }
+            mGradient = res.getDrawable(gradientResourceId);
+            mInterpolator = new LinearInterpolator();
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            // noop
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+            // noop
+        }
+
+        @Override
+        protected void onBoundsChange(Rect bounds) {
+            super.onBoundsChange(bounds);
+            mGradient.setBounds(bounds);
+        }
+
+        public void applyModeBackground(int oldMode, int newMode, boolean animate) {
+            if (mMode == newMode) return;
+            mMode = newMode;
+            mAnimating = animate;
+            if (animate) {
+                long now = SystemClock.elapsedRealtime();
+                mStartTime = now;
+                mEndTime = now + BACKGROUND_DURATION;
+                mGradientAlphaStart = mGradientAlpha;
+                mColorStart = mColor;
+            }
+            invalidateSelf();
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+
+        public void finishAnimation() {
+            if (mAnimating) {
+                mAnimating = false;
+                invalidateSelf();
+            }
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            int targetGradientAlpha = 0, targetColor = 0;
+            if (mMode == MODE_TRANSLUCENT) {
+                targetGradientAlpha = 0xff;
+            } else if (mMode == MODE_SEMI_TRANSPARENT) {
+                targetColor = mSemiTransparent;
+            } else {
+                targetColor = mOpaque;
+            }
+            if (!mAnimating) {
+                mColor = targetColor;
+                mGradientAlpha = targetGradientAlpha;
+            } else {
+                final long now = SystemClock.elapsedRealtime();
+                if (now >= mEndTime) {
+                    mAnimating = false;
+                    mColor = targetColor;
+                    mGradientAlpha = targetGradientAlpha;
+                } else {
+                    final float t = (now - mStartTime) / (float)(mEndTime - mStartTime);
+                    final float v = Math.max(0, Math.min(mInterpolator.getInterpolation(t), 1));
+                    mGradientAlpha = (int)(v * targetGradientAlpha + mGradientAlphaStart * (1 - v));
+                    mColor = Color.argb(
+                          (int)(v * Color.alpha(targetColor) + Color.alpha(mColorStart) * (1 - v)),
+                          (int)(v * Color.red(targetColor) + Color.red(mColorStart) * (1 - v)),
+                          (int)(v * Color.green(targetColor) + Color.green(mColorStart) * (1 - v)),
+                          (int)(v * Color.blue(targetColor) + Color.blue(mColorStart) * (1 - v)));
+                }
+            }
+            if (mGradientAlpha > 0) {
+                mGradient.setAlpha(mGradientAlpha);
+                mGradient.draw(canvas);
+            }
+            if (Color.alpha(mColor) > 0) {
+                canvas.drawColor(mColor);
+            }
+            if (mAnimating) {
+                invalidateSelf();  // keep going
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 925179d..39a9ba7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1945,6 +1945,13 @@
         transitions.transitionTo(mode, anim);
     }
 
+    private void finishBarAnimations() {
+        mStatusBarView.getBarTransitions().finishAnimations();
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getBarTransitions().finishAnimations();
+        }
+    }
+
     private final Runnable mCheckBarModes = new Runnable() {
         @Override
         public void run() {
@@ -2449,6 +2456,7 @@
                 makeExpandedInvisible();
                 notifyNavigationBarScreenOn(false);
                 notifyHeadsUpScreenOn(false);
+                finishBarAnimations();
             }
             else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                 mScreenOn = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index d9ac7e4..d0e9a99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -170,6 +170,9 @@
         mBar.makeExpandedInvisibleSoon();
         mFadingPanel = null;
         mLastFullyOpenedPanel = null;
+        if (mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
+            mBar.mStatusBarWindow.setBackgroundColor(0);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 5423bb6..37504fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -630,8 +630,19 @@
                     return true; // Consume click
                 }} );
         }
-        mModel.addLocationTile(locationTile,
-                new QuickSettingsModel.BasicRefreshCallback(locationTile));
+        mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView unused, State state) {
+                locationTile.setImageResource(state.iconId);
+                String locationState = mContext.getString(
+                        (state.enabled) ? R.string.accessibility_desc_on
+                                : R.string.accessibility_desc_off);
+                locationTile.setContentDescription(mContext.getString(
+                        R.string.accessibility_quick_settings_location,
+                        locationState));
+                locationTile.setText(state.label);
+            }
+        });
         parent.addView(locationTile);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 2026102..15d655c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -280,7 +280,7 @@
         mUserTracker = new CurrentUserTracker(mContext) {
             public void onUserSwitched(int newUserId) {
                 mBrightnessObserver.startObserving();
-                onRotationLockChanged();
+                refreshRotationLockTile();
                 onBrightnessLevelChanged();
                 onNextAlarmChanged();
                 onBugreportChanged();
diff --git a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
index dfdcdad5..3e57a77 100644
--- a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
@@ -201,13 +201,20 @@
         private ValueAnimator mColorAnim;
         private ViewGroup mClingLayout;
 
+        private Runnable mUpdateLayoutRunnable = new Runnable() {
+            @Override
+            public void run() {
+                if (mClingLayout != null && mClingLayout.getParent() != null) {
+                    mClingLayout.setLayoutParams(getBubbleLayoutParams());
+                }
+            }
+        };
+
         private BroadcastReceiver mReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
-                    if (mClingLayout != null && mClingLayout.getParent() != null) {
-                        mClingLayout.setLayoutParams(getBubbleLayoutParams());
-                    }
+                    post(mUpdateLayoutRunnable);
                 }
             }
         };
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index eba689d..44fc1f8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -23,6 +23,8 @@
 import static android.view.WindowManager.LayoutParams.*;
 
 import android.view.ViewConfiguration;
+
+import com.android.internal.R;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
 import com.android.internal.view.menu.ContextMenuBuilder;
@@ -1920,6 +1922,11 @@
         private PopupWindow mActionModePopup;
         private Runnable mShowActionModePopup;
 
+        // View added at runtime to draw under the status bar area
+        private View mStatusGuard;
+        // View added at runtime to draw under the navigation bar area
+        private View mNavigationGuard;
+
         public DecorView(Context context, int featureId) {
             super(context);
             mFeatureId = featureId;
@@ -2479,12 +2486,91 @@
         @Override
         protected boolean fitSystemWindows(Rect insets) {
             mFrameOffsets.set(insets);
+            updateStatusGuard(insets);
+            updateNavigationGuard(insets);
             if (getForeground() != null) {
                 drawableChanged();
             }
             return super.fitSystemWindows(insets);
         }
 
+        private void updateStatusGuard(Rect insets) {
+            boolean showStatusGuard = false;
+            // Show the status guard when the non-overlay contextual action bar is showing
+            if (mActionModeView != null) {
+                if (mActionModeView.getLayoutParams() instanceof MarginLayoutParams) {
+                    MarginLayoutParams mlp = (MarginLayoutParams) mActionModeView.getLayoutParams();
+                    boolean mlpChanged = false;
+                    final boolean nonOverlayShown =
+                            (getLocalFeatures() & (1 << FEATURE_ACTION_MODE_OVERLAY)) == 0
+                            && mActionModeView.isShown();
+                    if (nonOverlayShown) {
+                        // set top margin to top insets, show status guard
+                        if (mlp.topMargin != insets.top) {
+                            mlpChanged = true;
+                            mlp.topMargin = insets.top;
+                            if (mStatusGuard == null) {
+                                mStatusGuard = new View(mContext);
+                                mStatusGuard.setBackgroundColor(mContext.getResources()
+                                        .getColor(R.color.input_method_navigation_guard));
+                                addView(mStatusGuard, new LayoutParams(
+                                        LayoutParams.MATCH_PARENT, mlp.topMargin,
+                                        Gravity.START | Gravity.TOP));
+                            } else {
+                                LayoutParams lp = (LayoutParams) mStatusGuard.getLayoutParams();
+                                if (lp.height != mlp.topMargin) {
+                                    lp.height = mlp.topMargin;
+                                    mStatusGuard.setLayoutParams(lp);
+                                }
+                            }
+                        }
+                        insets.top = 0;  // consume top insets
+                        showStatusGuard = true;
+                    } else {
+                        // reset top margin
+                        if (mlp.topMargin != 0) {
+                            mlpChanged = true;
+                            mlp.topMargin = 0;
+                        }
+                    }
+                    if (mlpChanged) {
+                        mActionModeView.setLayoutParams(mlp);
+                    }
+                }
+            }
+            if (mStatusGuard != null) {
+                mStatusGuard.setVisibility(showStatusGuard ? View.VISIBLE : View.GONE);
+            }
+        }
+
+        private void updateNavigationGuard(Rect insets) {
+            // IMEs lay out below the nav bar, but the content view must not (for back compat)
+            if (getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD) {
+                // prevent the content view from including the nav bar height
+                if (mContentParent != null) {
+                    if (mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
+                        MarginLayoutParams mlp =
+                                (MarginLayoutParams) mContentParent.getLayoutParams();
+                        mlp.bottomMargin = insets.bottom;
+                        mContentParent.setLayoutParams(mlp);
+                    }
+                }
+                // position the navigation guard view, creating it if necessary
+                if (mNavigationGuard == null) {
+                    mNavigationGuard = new View(mContext);
+                    mNavigationGuard.setBackgroundColor(mContext.getResources()
+                            .getColor(R.color.input_method_navigation_guard));
+                    addView(mNavigationGuard, new LayoutParams(
+                            LayoutParams.MATCH_PARENT, insets.bottom,
+                            Gravity.START | Gravity.BOTTOM));
+                } else {
+                    LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
+                    lp.height = insets.bottom;
+                    mNavigationGuard.setLayoutParams(lp);
+                }
+            }
+        }
+
         private void drawableChanged() {
             if (mChanging) {
                 return;
@@ -2661,6 +2747,7 @@
             }
 
             public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+                requestFitSystemWindows();
                 return mWrapped.onPrepareActionMode(mode, menu);
             }
 
@@ -2687,6 +2774,7 @@
                     }
                 }
                 mActionMode = null;
+                requestFitSystemWindows();
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1c43014..dcaf3d6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -4668,6 +4668,9 @@
 
     /** {@inheritDoc} */
     public void systemBooted() {
+        if (mKeyguardDelegate != null) {
+            mKeyguardDelegate.onBootCompleted();
+        }
         synchronized (mLock) {
             mSystemBooted = true;
         }
@@ -5183,7 +5186,8 @@
         final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
         return mNavigationBar != null
                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
-                && (vis & flags) != 0;
+                && (vis & flags) != 0
+                && canHideNavigationBar();
     }
 
     /**
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 56a282b..bf22e2f 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -52,6 +52,7 @@
         public int offReason;
         public int currentUser;
         public boolean screenIsOn;
+        public boolean bootCompleted;
     };
 
     public interface ShowListener {
@@ -117,6 +118,9 @@
                 // This is used to hide the scrim once keyguard displays.
                 mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
             }
+            if (mKeyguardState.bootCompleted) {
+                mKeyguardService.onBootCompleted();
+            }
         }
 
         @Override
@@ -305,4 +309,11 @@
         });
     }
 
+    public void onBootCompleted() {
+        if (mKeyguardService != null) {
+            mKeyguardService.onBootCompleted();
+        }
+        mKeyguardState.bootCompleted = true;
+    }
+
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 83be1a8..9fb2a50 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -180,6 +180,14 @@
         }
     }
 
+    public void onBootCompleted() {
+        try {
+            mService.onBootCompleted();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
     public void showAssistant() {
         // Not used by PhoneWindowManager
     }
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 274009f..10a639e 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1699,7 +1699,7 @@
         // up with lots of events because the application is not responding.
         // This condition ensures that ANRs are detected reliably.
         if (!connection->waitQueue.isEmpty()
-                && currentTime >= connection->waitQueue.head->eventEntry->eventTime
+                && currentTime >= connection->waitQueue.head->deliveryTime
                         + STREAM_AHEAD_EVENT_TIMEOUT) {
             return false;
         }
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 3d804ef..b70a34e 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -385,10 +385,19 @@
             for (int i = 0; i < N; i++) {
                 Alarm a = batch.get(i);
                 long whenElapsed = convertToElapsed(a.when, a.type);
-                long maxElapsed = (a.whenElapsed == a.maxWhen)
-                        ? whenElapsed
-                                : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
-                setImplLocked(a.type, a.when, whenElapsed, maxElapsed,
+                final long maxElapsed;
+                if (a.whenElapsed == a.maxWhen) {
+                    // Exact
+                    maxElapsed = whenElapsed;
+                } else {
+                    // Not exact.  Preserve any explicit window, otherwise recalculate
+                    // the window based on the alarm's new futurity.  Note that this
+                    // reflects a policy of preferring timely to deferred delivery.
+                    maxElapsed = (a.windowLength > 0)
+                            ? (whenElapsed + a.windowLength)
+                            : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
+                }
+                setImplLocked(a.type, a.when, whenElapsed, a.windowLength, maxElapsed,
                         a.repeatInterval, a.operation, batch.standalone, doValidate, a.workSource);
             }
         }
@@ -556,15 +565,16 @@
                         + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
                         + " interval=" + interval + " standalone=" + isStandalone);
             }
-            setImplLocked(type, triggerAtTime, triggerElapsed, maxElapsed,
+            setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
                     interval, operation, isStandalone, true, workSource);
         }
     }
 
-    private void setImplLocked(int type, long when, long whenElapsed, long maxWhen, long interval,
-            PendingIntent operation, boolean isStandalone, boolean doValidate,
-            WorkSource workSource) {
-        Alarm a = new Alarm(type, when, whenElapsed, maxWhen, interval, operation, workSource);
+    private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
+            long maxWhen, long interval, PendingIntent operation, boolean isStandalone,
+            boolean doValidate, WorkSource workSource) {
+        Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
+                operation, workSource);
         removeLocked(operation);
 
         boolean reschedule;
@@ -1046,7 +1056,7 @@
                     // Also schedule its next recurrence
                     final long delta = alarm.count * alarm.repeatInterval;
                     final long nextElapsed = alarm.whenElapsed + delta;
-                    setImplLocked(alarm.type, alarm.when + delta, nextElapsed,
+                    setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
                             maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
                             alarm.repeatInterval, alarm.operation, batch.standalone, true,
                             alarm.workSource);
@@ -1077,17 +1087,19 @@
         public int type;
         public int count;
         public long when;
+        public long windowLength;
         public long whenElapsed;    // 'when' in the elapsed time base
         public long maxWhen;        // also in the elapsed time base
         public long repeatInterval;
         public PendingIntent operation;
         public WorkSource workSource;
         
-        public Alarm(int _type, long _when, long _whenElapsed, long _maxWhen,
+        public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
                 long _interval, PendingIntent _op, WorkSource _ws) {
             type = _type;
             when = _when;
             whenElapsed = _whenElapsed;
+            windowLength = _windowLength;
             maxWhen = _maxWhen;
             repeatInterval = _interval;
             operation = _op;
@@ -1112,6 +1124,7 @@
             pw.print(prefix); pw.print("type="); pw.print(type);
                     pw.print(" whenElapsed="); pw.print(whenElapsed);
                     pw.print(" when="); TimeUtils.formatDuration(when, now, pw);
+                    pw.print(" window="); pw.print(windowLength);
                     pw.print(" repeatInterval="); pw.print(repeatInterval);
                     pw.print(" count="); pw.println(count);
             pw.print(prefix); pw.print("operation="); pw.println(operation);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b5f0697..7c61c44 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -4467,8 +4467,9 @@
             mdst.enableMobileProvisioning(url);
         } else {
             if (DBG) log("handleMobileProvisioningAction: on default network");
-            Intent newIntent =
-                    new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+            Intent newIntent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
+                    Intent.CATEGORY_APP_BROWSER);
+            newIntent.setData(Uri.parse(url));
             newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
                     Intent.FLAG_ACTIVITY_NEW_TASK);
             try {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 794d274..562a50f 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -879,8 +879,12 @@
         final boolean isScreenSecurelyLocked =
                 isScreenLocked && mKeyguardManager.isKeyguardSecure();
         final boolean inputShown = mInputShown && (!isScreenLocked || mInputBoundToKeyguard);
-        mImeWindowVis = (!isScreenSecurelyLocked && (inputShown || hardKeyShown)) ?
-                (InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0;
+        final boolean inputActive = !isScreenSecurelyLocked && (inputShown || hardKeyShown);
+        // We assume the softkeyboard is shown when the input is active as long as the
+        // hard keyboard is not shown.
+        final boolean inputVisible = inputActive && !hardKeyShown;
+        mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0)
+                | (inputVisible ? InputMethodService.IME_VISIBLE : 0);
         updateImeWindowStatusLocked();
     }
 
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index c7ca1ea..e60231a 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -62,6 +62,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IMediaContainerService;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.NativeDaemonConnector.Command;
@@ -173,6 +174,8 @@
          * 600 series - Unsolicited broadcasts.
          */
         public static final int VolumeStateChange              = 605;
+        public static final int VolumeUuidChange               = 613;
+        public static final int VolumeUserLabelChange          = 614;
         public static final int VolumeDiskInserted             = 630;
         public static final int VolumeDiskRemoved              = 631;
         public static final int VolumeBadRemoval               = 632;
@@ -661,6 +664,7 @@
         final String oldState;
         synchronized (mVolumesLock) {
             oldState = mVolumeStates.put(path, state);
+            volume.setState(state);
         }
 
         if (state.equals(oldState)) {
@@ -801,6 +805,26 @@
             notifyVolumeStateChange(
                     cooked[2], cooked[3], Integer.parseInt(cooked[7]),
                             Integer.parseInt(cooked[10]));
+        } else if (code == VoldResponseCode.VolumeUuidChange) {
+            // Format: nnn <label> <path> <uuid>
+            final String path = cooked[2];
+            final String uuid = (cooked.length > 3) ? cooked[3] : null;
+
+            final StorageVolume vol = mVolumesByPath.get(path);
+            if (vol != null) {
+                vol.setUuid(uuid);
+            }
+
+        } else if (code == VoldResponseCode.VolumeUserLabelChange) {
+            // Format: nnn <label> <path> <label>
+            final String path = cooked[2];
+            final String userLabel = (cooked.length > 3) ? cooked[3] : null;
+
+            final StorageVolume vol = mVolumesByPath.get(path);
+            if (vol != null) {
+                vol.setUserLabel(userLabel);
+            }
+
         } else if ((code == VoldResponseCode.VolumeDiskInserted) ||
                    (code == VoldResponseCode.VolumeDiskRemoved) ||
                    (code == VoldResponseCode.VolumeBadRemoval)) {
@@ -1230,6 +1254,7 @@
 
                             // Until we hear otherwise, treat as unmounted
                             mVolumeStates.put(volume.getPath(), Environment.MEDIA_UNMOUNTED);
+                            volume.setState(Environment.MEDIA_UNMOUNTED);
                         }
                     }
 
@@ -1273,6 +1298,7 @@
         } else {
             // Place stub status for early callers to find
             mVolumeStates.put(volume.getPath(), Environment.MEDIA_MOUNTED);
+            volume.setState(Environment.MEDIA_MOUNTED);
         }
     }
 
@@ -2743,54 +2769,59 @@
     }
 
     @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump ActivityManager from from pid="
-                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
-                    + " without permission " + android.Manifest.permission.DUMP);
-            return;
-        }
+    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ", 160);
 
         synchronized (mObbMounts) {
-            pw.println("  mObbMounts:");
-
-            final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet().iterator();
+            pw.println("mObbMounts:");
+            pw.increaseIndent();
+            final Iterator<Entry<IBinder, List<ObbState>>> binders = mObbMounts.entrySet()
+                    .iterator();
             while (binders.hasNext()) {
                 Entry<IBinder, List<ObbState>> e = binders.next();
-                pw.print("    Key="); pw.println(e.getKey().toString());
+                pw.println(e.getKey() + ":");
+                pw.increaseIndent();
                 final List<ObbState> obbStates = e.getValue();
                 for (final ObbState obbState : obbStates) {
-                    pw.print("      "); pw.println(obbState.toString());
+                    pw.println(obbState);
                 }
+                pw.decreaseIndent();
             }
+            pw.decreaseIndent();
 
-            pw.println("");
-            pw.println("  mObbPathToStateMap:");
+            pw.println();
+            pw.println("mObbPathToStateMap:");
+            pw.increaseIndent();
             final Iterator<Entry<String, ObbState>> maps = mObbPathToStateMap.entrySet().iterator();
             while (maps.hasNext()) {
                 final Entry<String, ObbState> e = maps.next();
-                pw.print("    "); pw.print(e.getKey());
-                pw.print(" -> "); pw.println(e.getValue().toString());
+                pw.print(e.getKey());
+                pw.print(" -> ");
+                pw.println(e.getValue());
             }
+            pw.decreaseIndent();
         }
 
-        pw.println("");
-
         synchronized (mVolumesLock) {
-            pw.println("  mVolumes:");
-
-            final int N = mVolumes.size();
-            for (int i = 0; i < N; i++) {
-                final StorageVolume v = mVolumes.get(i);
-                pw.print("    ");
-                pw.println(v.toString());
-                pw.println("      state=" + mVolumeStates.get(v.getPath()));
+            pw.println();
+            pw.println("mVolumes:");
+            pw.increaseIndent();
+            for (StorageVolume volume : mVolumes) {
+                pw.println(volume);
+                pw.increaseIndent();
+                pw.println("Current state: " + mVolumeStates.get(volume.getPath()));
+                pw.decreaseIndent();
             }
+            pw.decreaseIndent();
         }
 
         pw.println();
-        pw.println("  mConnection:");
+        pw.println("mConnection:");
+        pw.increaseIndent();
         mConnector.dump(fd, pw, args);
+        pw.decreaseIndent();
     }
 
     /** {@inheritDoc} */
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 616090e..8054788 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -58,7 +58,14 @@
     // Set this to true to have the watchdog record kernel thread stacks when it fires
     static final boolean RECORD_KERNEL_THREADS = true;
 
-    static final int TIME_TO_WAIT = DB ? 5*1000 : 30*1000;
+    static final long DEFAULT_TIMEOUT = DB ? 10*1000 : 60*1000;
+    static final long CHECK_INTERVAL = DEFAULT_TIMEOUT / 2;
+
+    // These are temporally ordered: larger values as lateness increases
+    static final int COMPLETED = 0;
+    static final int WAITING = 1;
+    static final int WAITED_HALF = 2;
+    static final int OVERDUE = 3;
 
     static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {
         "/system/bin/mediaserver",
@@ -87,13 +94,17 @@
     public final class HandlerChecker implements Runnable {
         private final Handler mHandler;
         private final String mName;
+        private final long mWaitMax;
         private final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>();
         private boolean mCompleted;
         private Monitor mCurrentMonitor;
+        private long mStartTime;
 
-        HandlerChecker(Handler handler, String name) {
+        HandlerChecker(Handler handler, String name, long waitMaxMillis) {
             mHandler = handler;
             mName = name;
+            mWaitMax = waitMaxMillis;
+            mCompleted = true;
         }
 
         public void addMonitor(Monitor monitor) {
@@ -111,13 +122,34 @@
                 mCompleted = true;
                 return;
             }
+
+            if (!mCompleted) {
+                // we already have a check in flight, so no need
+                return;
+            }
+
             mCompleted = false;
             mCurrentMonitor = null;
+            mStartTime = SystemClock.uptimeMillis();
             mHandler.postAtFrontOfQueue(this);
         }
 
-        public boolean isCompletedLocked() {
-            return mCompleted;
+        public boolean isOverdueLocked() {
+            return (!mCompleted) && (SystemClock.uptimeMillis() > mStartTime + mWaitMax);
+        }
+
+        public int getCompletionStateLocked() {
+            if (mCompleted) {
+                return COMPLETED;
+            } else {
+                long latency = SystemClock.uptimeMillis() - mStartTime;
+                if (latency < mWaitMax/2) {
+                    return WAITING;
+                } else if (latency < mWaitMax) {
+                    return WAITED_HALF;
+                }
+            }
+            return OVERDUE;
         }
 
         public Thread getThread() {
@@ -186,16 +218,19 @@
 
         // The shared foreground thread is the main checker.  It is where we
         // will also dispatch monitor checks and do other work.
-        mMonitorChecker = new HandlerChecker(FgThread.getHandler(), "foreground thread");
+        mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
+                "foreground thread", DEFAULT_TIMEOUT);
         mHandlerCheckers.add(mMonitorChecker);
         // Add checker for main thread.  We only do a quick check since there
         // can be UI running on the thread.
         mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),
-                "main thread"));
+                "main thread", DEFAULT_TIMEOUT));
         // Add checker for shared UI thread.
-        mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), "ui thread"));
+        mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
+                "ui thread", DEFAULT_TIMEOUT));
         // And also check IO thread.
-        mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), "i/o thread"));
+        mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
+                "i/o thread", DEFAULT_TIMEOUT));
     }
 
     public void init(Context context, BatteryService battery,
@@ -242,11 +277,15 @@
     }
 
     public void addThread(Handler thread, String name) {
+        addThread(thread, name, DEFAULT_TIMEOUT);
+    }
+
+    public void addThread(Handler thread, String name, long timeoutMillis) {
         synchronized (this) {
             if (isAlive()) {
                 throw new RuntimeException("Threads can't be added once the Watchdog is running");
             }
-            mHandlerCheckers.add(new HandlerChecker(thread, name));
+            mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));
         }
     }
 
@@ -259,21 +298,20 @@
         pms.reboot(false, reason, false);
     }
 
-    private boolean haveAllCheckersCompletedLocked() {
+    private int evaluateCheckerCompletionLocked() {
+        int state = COMPLETED;
         for (int i=0; i<mHandlerCheckers.size(); i++) {
             HandlerChecker hc = mHandlerCheckers.get(i);
-            if (!hc.isCompletedLocked()) {
-                return false;
-            }
+            state = Math.max(state, hc.getCompletionStateLocked());
         }
-        return true;
+        return state;
     }
 
     private ArrayList<HandlerChecker> getBlockedCheckersLocked() {
         ArrayList<HandlerChecker> checkers = new ArrayList<HandlerChecker>();
         for (int i=0; i<mHandlerCheckers.size(); i++) {
             HandlerChecker hc = mHandlerCheckers.get(i);
-            if (!hc.isCompletedLocked()) {
+            if (hc.isOverdueLocked()) {
                 checkers.add(hc);
             }
         }
@@ -299,14 +337,12 @@
             final String subject;
             final boolean allowRestart;
             synchronized (this) {
-                long timeout = TIME_TO_WAIT;
-                if (!waitedHalf) {
-                    // If we are not at the half-point of waiting, perform a
-                    // new set of checks.  Otherwise we are still waiting for a previous set.
-                    for (int i=0; i<mHandlerCheckers.size(); i++) {
-                        HandlerChecker hc = mHandlerCheckers.get(i);
-                        hc.scheduleCheckLocked();
-                    }
+                long timeout = CHECK_INTERVAL;
+                // Make sure we (re)spin the checkers that have become idle within
+                // this wait-and-check interval
+                for (int i=0; i<mHandlerCheckers.size(); i++) {
+                    HandlerChecker hc = mHandlerCheckers.get(i);
+                    hc.scheduleCheckLocked();
                 }
 
                 // NOTE: We use uptimeMillis() here because we do not want to increment the time we
@@ -320,26 +356,31 @@
                     } catch (InterruptedException e) {
                         Log.wtf(TAG, e);
                     }
-                    timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
+                    timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);
                 }
 
-                if (haveAllCheckersCompletedLocked()) {
-                    // The monitors have returned.
+                final int waitState = evaluateCheckerCompletionLocked();
+                if (waitState == COMPLETED) {
+                    // The monitors have returned; reset
                     waitedHalf = false;
                     continue;
-                }
-
-                if (!waitedHalf) {
-                    // We've waited half the deadlock-detection interval.  Pull a stack
-                    // trace and wait another half.
-                    ArrayList<Integer> pids = new ArrayList<Integer>();
-                    pids.add(Process.myPid());
-                    ActivityManagerService.dumpStackTraces(true, pids, null, null,
-                            NATIVE_STACKS_OF_INTEREST);
-                    waitedHalf = true;
+                } else if (waitState == WAITING) {
+                    // still waiting but within their configured intervals; back off and recheck
+                    continue;
+                } else if (waitState == WAITED_HALF) {
+                    if (!waitedHalf) {
+                        // We've waited half the deadlock-detection interval.  Pull a stack
+                        // trace and wait another half.
+                        ArrayList<Integer> pids = new ArrayList<Integer>();
+                        pids.add(Process.myPid());
+                        ActivityManagerService.dumpStackTraces(true, pids, null, null,
+                                NATIVE_STACKS_OF_INTEREST);
+                        waitedHalf = true;
+                    }
                     continue;
                 }
 
+                // something is overdue!
                 blockedCheckers = getBlockedCheckersLocked();
                 subject = describeCheckersLocked(blockedCheckers);
                 allowRestart = mAllowRestart;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3ba9098..8b7fd8e 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7224,7 +7224,13 @@
                 if (DEBUG_MU)
                     Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
                 app.pubProviders.put(cpi.name, cpr);
-                app.addPackage(cpi.applicationInfo.packageName, mProcessStats);
+                if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
+                    // Don't add this if it is a platform component that is marked
+                    // to run in multiple processes, because this is actually
+                    // part of the framework so doesn't make sense to track as a
+                    // separate apk in the process.
+                    app.addPackage(cpi.applicationInfo.packageName, mProcessStats);
+                }
                 ensurePackageDexOpt(cpi.applicationInfo.packageName);
             }
         }
@@ -12777,7 +12783,8 @@
                             + ") when registering receiver " + receiver);
                 }
                 if (callerApp.info.uid != Process.SYSTEM_UID &&
-                        !callerApp.pkgList.containsKey(callerPackage)) {
+                        !callerApp.pkgList.containsKey(callerPackage) &&
+                        !"android".equals(callerPackage)) {
                     throw new SecurityException("Given caller package " + callerPackage
                             + " is not running in process " + callerApp);
                 }
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index cf686672..49f29fe 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -480,7 +480,12 @@
 
     void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
         if (task != null && task.removeActivity(this)) {
-            mStackSupervisor.removeTask(task);
+            if (task != newTask) {
+                mStackSupervisor.removeTask(task);
+            } else {
+                Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
+                        (newTask == null ? null : newTask.stack));
+            }
         }
         if (inHistory && !finishing) {
             if (task != null) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 0397fd5..2e5dedf 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -740,7 +740,10 @@
         prev.state = ActivityState.PAUSING;
         prev.task.touchActiveTime();
         clearLaunchTime(prev);
-        prev.updateThumbnail(screenshotActivities(prev), null);
+        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
+        if (next == null || next.task != prev.task) {
+            prev.updateThumbnail(screenshotActivities(prev), null);
+        }
         stopFullyDrawnTraceIfNeeded();
 
         mService.updateCpuStats();
@@ -977,6 +980,40 @@
     }
 
     /**
+     * Determine if home should be visible below the passed record.
+     * @param record activity we are querying for.
+     * @return true if home is visible below the passed activity, false otherwise.
+     */
+    boolean isActivityOverHome(ActivityRecord record) {
+        // Start at record and go down, look for either home or a visible fullscreen activity.
+        final TaskRecord recordTask = record.task;
+        for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) {
+            TaskRecord task = mTaskHistory.get(taskNdx);
+            final ArrayList<ActivityRecord> activities = task.mActivities;
+            final int startNdx =
+                    task == recordTask ? activities.indexOf(record) : activities.size() - 1;
+            for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = activities.get(activityNdx);
+                if (r.isHomeActivity()) {
+                    return true;
+                }
+                if (!r.finishing && r.visible && r.fullscreen) {
+                    // Passed activity is over a visible fullscreen activity.
+                    return false;
+                }
+            }
+            if (task.mOnTopOfHome) {
+                // Got to the bottom of a task on top of home without finding a visible fullscreen
+                // activity. Home is visible.
+                return true;
+            }
+        }
+        // Got to the bottom of this stack and still don't know. If this is over the home stack
+        // then record is over home. May not work if we ever get more than two layers.
+        return mStackSupervisor.isFrontStack(this);
+    }
+
+    /**
      * Version of ensureActivitiesVisible that can easily be called anywhere.
      */
     final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
@@ -1101,24 +1138,10 @@
                         // At this point, nothing else needs to be shown
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
                         behindFullscreen = true;
-                    } else if (task.mOnTopOfHome) {
-                        // Work our way down from r to bottom of task and see if there are any
-                        // visible activities below r.
-                        int rIndex = task.mActivities.indexOf(r);
-                        for ( --rIndex; rIndex >= 0; --rIndex) {
-                            final ActivityRecord blocker = task.mActivities.get(rIndex);
-                            if (!blocker.finishing) {
-                                if (DEBUG_VISBILITY) Slog.v(TAG, "Home visibility for " +
-                                        r + " blocked by " + blocker);
-                                break;
-                            }
-                        }
-                        if (rIndex < 0) {
-                            // Got to task bottom without finding a visible activity, show home.
-                            if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
-                            showHomeBehindStack = true;
-                            behindFullscreen = true;
-                        }
+                    } else if (isActivityOverHome(r)) {
+                        if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
+                        showHomeBehindStack = true;
+                        behindFullscreen = true;
                     }
                 } else {
                     if (DEBUG_VISBILITY) Slog.v(
@@ -2174,6 +2197,19 @@
         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
     }
 
+    private void adjustFocusedActivityLocked(ActivityRecord r) {
+        if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
+            ActivityRecord next = topRunningActivityLocked(null);
+            if (next != r) {
+                final TaskRecord task = r.task;
+                if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) {
+                    mStackSupervisor.moveHomeToTop();
+                }
+            }
+            mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked());
+        }
+    }
+
     final void stopActivityLocked(ActivityRecord r) {
         if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
@@ -2193,11 +2229,7 @@
         }
 
         if (r.app != null && r.app.thread != null) {
-            if (mStackSupervisor.isFrontStack(this)) {
-                if (mService.mFocusedActivity == r) {
-                    mService.setFocusedActivityLocked(topRunningActivityLocked(null));
-                }
-            }
+            adjustFocusedActivityLocked(r);
             r.resumeKeyDispatchingLocked();
             try {
                 r.stopped = false;
@@ -2376,11 +2408,8 @@
         }
 
         r.pauseKeyDispatchingLocked();
-        if (mStackSupervisor.isFrontStack(this)) {
-            if (mService.mFocusedActivity == r) {
-                mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked());
-            }
-        }
+
+        adjustFocusedActivityLocked(r);
 
         finishActivityResultsLocked(r, resultCode, resultData);
 
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 523015d..b510643 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1051,7 +1051,14 @@
 
         if (app != null && app.thread != null) {
             try {
-                app.addPackage(r.info.packageName, mService.mProcessStats);
+                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
+                        || !"android".equals(r.info.packageName)) {
+                    // Don't add this if it is a platform component that is marked
+                    // to run in multiple processes, because this is actually
+                    // part of the framework so doesn't make sense to track as a
+                    // separate apk in the process.
+                    app.addPackage(r.info.packageName, mService.mProcessStats);
+                }
                 realStartActivityLocked(r, app, andResume, checkConfig);
                 return;
             } catch (RemoteException e) {
@@ -1254,15 +1261,16 @@
         final TaskRecord task = r.task;
         if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
             if (task != null) {
-                if (mFocusedStack != task.stack) {
+                final ActivityStack taskStack = task.stack;
+                if (mFocusedStack != taskStack) {
                     if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                             "adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
-                    mFocusedStack = task.stack;
+                    mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
                 } else {
                     if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                         "adjustStackFocus: Focused stack already=" + mFocusedStack);
                 }
-                return mFocusedStack;
+                return taskStack;
             }
 
             if (mFocusedStack != null) {
@@ -1282,8 +1290,8 @@
             }
 
             // Time to create the first app stack for this user.
-            int stackId = mService.createStack(-1, HOME_STACK_ID,
-                StackBox.TASK_STACK_GOES_OVER, 1.0f);
+            int stackId =
+                    mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
             if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
                     " stackId=" + stackId);
             mFocusedStack = getStack(stackId);
@@ -1308,7 +1316,8 @@
             if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
                     "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
                     " Callers=" + Debug.getCallers(3));
-            mFocusedStack = r.task.stack;
+            final ActivityStack taskStack = r.task.stack;
+            mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
             if (mStackState != STACK_STATE_HOME_IN_BACK) {
                 if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
                         stackStateToString(mStackState) + " new=" +
@@ -2367,12 +2376,13 @@
     }
 
     public void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
+        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
                 pw.println(mDismissKeyguardOnNextActivity);
-        pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
-        pw.print(prefix); pw.println("mSleepTimeout: " + mSleepTimeout);
-        pw.print(prefix); pw.println("mCurTaskId: " + mCurTaskId);
-        pw.print(prefix); pw.println("mUserStackInFront: " + mUserStackInFront);
+        pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
+                pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
+        pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
+        pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
+        pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
     }
 
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 50a7b5c..8d16880 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -529,6 +529,33 @@
         }
     }
 
+    private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
+            String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
+            boolean dumpAll, boolean activeOnly) {
+        ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
+                - (ProcessStats.COMMIT_PERIOD/2));
+        if (pfd == null) {
+            pw.println("Unable to build stats!");
+            return;
+        }
+        ProcessStats stats = new ProcessStats(false);
+        InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        stats.read(stream);
+        if (stats.mReadError != null) {
+            pw.print("Failure reading: "); pw.println(stats.mReadError);
+            return;
+        }
+        if (isCompact) {
+            stats.dumpCheckinLocked(pw, reqPackage);
+        } else {
+            if (dumpDetails || dumpFullDetails) {
+                stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
+            } else {
+                stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
+            }
+        }
+    }
+
     static private void dumpHelp(PrintWriter pw) {
         pw.println("Process stats (procstats) dump options:");
         pw.println("    [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
@@ -789,28 +816,8 @@
             }
             return;
         } else if (aggregateHours != 0) {
-            ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
-                    - (ProcessStats.COMMIT_PERIOD/2));
-            if (pfd == null) {
-                pw.println("Unable to build stats!");
-                return;
-            }
-            ProcessStats stats = new ProcessStats(false);
-            InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
-            stats.read(stream);
-            if (stats.mReadError != null) {
-                pw.print("Failure reading: "); pw.println(stats.mReadError);
-                return;
-            }
-            if (isCompact) {
-                stats.dumpCheckinLocked(pw, reqPackage);
-            } else {
-                if (dumpDetails || dumpFullDetails) {
-                    stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
-                } else {
-                    stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
-                }
-            }
+            dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
+                    dumpDetails, dumpFullDetails, dumpAll, activeOnly);
             return;
         }
 
@@ -875,6 +882,19 @@
             }
         }
         if (!isCheckin) {
+            if (dumpAll) {
+                if (sepNeeded) {
+                    pw.println();
+                    pw.println("AGGREGATED OVER LAST 24 HOURS:");
+                }
+                dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
+                        dumpDetails, dumpFullDetails, dumpAll, activeOnly);
+                pw.println();
+                pw.println("AGGREGATED OVER LAST 3 HOURS:");
+                dumpAggregatedStats(pw, 3, now, reqPackage, isCompact,
+                        dumpDetails, dumpFullDetails, dumpAll, activeOnly);
+                sepNeeded = true;
+            }
             synchronized (mAm) {
                 if (isCompact) {
                     mProcessStats.dumpCheckinLocked(pw, reqPackage);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index fb6e9edc..a781d5f 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -221,6 +221,14 @@
     static final int REMOVE_CHATTY = 1<<16;
 
     /**
+     * Timeout (in milliseconds) after which the watchdog should declare that
+     * our handler thread is wedged.  The usual default for such things is one
+     * minute but we sometimes do very lengthy I/O operations on this thread,
+     * such as installing multi-gigabyte applications, so ours needs to be longer.
+     */
+    private static final long WATCHDOG_TIMEOUT = 1000*60*10;     // ten minutes
+
+    /**
      * Whether verification is enabled by default.
      */
     private static final boolean DEFAULT_VERIFY_ENABLE = true;
@@ -1115,7 +1123,8 @@
         synchronized (mPackages) {
             mHandlerThread.start();
             mHandler = new PackageHandler(mHandlerThread.getLooper());
-            Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName());
+            Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName(),
+                    WATCHDOG_TIMEOUT);
 
             File dataDir = Environment.getDataDirectory();
             mAppDataDir = new File(dataDir, "data");
@@ -3585,7 +3594,13 @@
                                 + ps.name + " changing from " + updatedPkg.codePathString
                                 + " to " + scanFile);
                         updatedPkg.codePath = scanFile;
-                        updatedPkg.codePathString = scanFile.toString();                        
+                        updatedPkg.codePathString = scanFile.toString();
+                        // This is the point at which we know that the system-disk APK
+                        // for this package has moved during a reboot (e.g. due to an OTA),
+                        // so we need to reevaluate it for privilege policy.
+                        if (locationIsPrivileged(scanFile)) {
+                            updatedPkg.pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
+                        }
                     }
                     updatedPkg.pkg = pkg;
                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
@@ -5566,9 +5581,9 @@
                         // version of the one on the data partition, but which
                         // granted a new system permission that it didn't have
                         // before.  In this case we do want to allow the app to
-                        // now get the new permission if the new system-partition
-                        // apk is privileged to get it.
-                        if (sysPs.pkg != null && isPrivilegedApp(pkg)) {
+                        // now get the new permission if the ancestral apk is
+                        // privileged to get it.
+                        if (sysPs.pkg != null && sysPs.isPrivileged()) {
                             for (int j=0;
                                     j<sysPs.pkg.requestedPermissions.size(); j++) {
                                 if (perm.equals(
@@ -9370,7 +9385,7 @@
         }
     }
 
-    boolean locationIsPrivileged(File path) {
+    static boolean locationIsPrivileged(File path) {
         try {
             final String privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app")
                     .getCanonicalPath();
diff --git a/services/java/com/android/server/pm/PackageSetting.java b/services/java/com/android/server/pm/PackageSetting.java
index b6f9f5b..b447861 100644
--- a/services/java/com/android/server/pm/PackageSetting.java
+++ b/services/java/com/android/server/pm/PackageSetting.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
 
 import java.io.File;
@@ -56,4 +57,8 @@
     public int[] getGids() {
         return sharedUser != null ? sharedUser.gids : gids;
     }
+
+    public boolean isPrivileged() {
+        return (pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+    }
 }
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 92fc6a4..d3ccba6 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -426,12 +426,12 @@
                         + "; replacing with new");
                 p = null;
             } else {
-                if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
-                    // If what we are scanning is a system package, then
-                    // make it so, regardless of whether it was previously
-                    // installed only in the data partition.
-                    p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
-                }
+                // If what we are scanning is a system (and possibly privileged) package,
+                // then make it so, regardless of whether it was previously installed only
+                // in the data partition.
+                final int sysPrivFlags = pkgFlags
+                        & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PRIVILEGED);
+                p.pkgFlags |= sysPrivFlags;
             }
         }
         if (p == null) {
@@ -2070,8 +2070,10 @@
                 if (intent.getAction() != null) {
                     filter.addAction(intent.getAction());
                 }
-                for (String cat : intent.getCategories()) {
-                    filter.addCategory(cat);
+                if (intent.getCategories() != null) {
+                    for (String cat : intent.getCategories()) {
+                        filter.addCategory(cat);
+                    }
                 }
                 if ((flags&PackageManager.MATCH_DEFAULT_ONLY) != 0) {
                     filter.addCategory(Intent.CATEGORY_DEFAULT);
@@ -2088,6 +2090,13 @@
                 if (path != null) {
                     filter.addDataPath(path);
                 }
+                if (intent.getType() != null) {
+                    try {
+                        filter.addDataType(intent.getType());
+                    } catch (IntentFilter.MalformedMimeTypeException ex) {
+                        Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn);
+                    }
+                }
                 PreferredActivity pa = new PreferredActivity(filter, match, set, cn, true);
                 editPreferredActivitiesLPw(userId).addFilter(pa);
             } else if (!haveNonSys) {
@@ -2210,7 +2219,11 @@
 
         int pkgFlags = 0;
         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
-        PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
+        final File codePathFile = new File(codePathStr);
+        if (PackageManagerService.locationIsPrivileged(codePathFile)) {
+            pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
+        }
+        PackageSetting ps = new PackageSetting(name, realName, codePathFile,
                 new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
@@ -2266,6 +2279,7 @@
                 XmlUtils.skipCurrentTag(parser);
             }
         }
+
         mDisabledSysPackages.put(name, ps);
     }
 
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 8fbde14..da9548f 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -747,6 +747,21 @@
     }
 
     @Override // Binder call
+    public void updateWakeLockUids(IBinder lock, int[] uids) {
+        WorkSource ws = null;
+
+        if (uids != null) {
+            ws = new WorkSource();
+            // XXX should WorkSource have a way to set uids as an int[] instead of adding them
+            // one at a time?
+            for (int i = 0; i < uids.length; i++) {
+                ws.add(uids[i]);
+            }
+        }
+        updateWakeLockWorkSource(lock, ws);
+    }
+
+    @Override // Binder call
     public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
         if (lock == null) {
             throw new IllegalArgumentException("lock must not be null");
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index edd6b25..8a3997a 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -361,12 +361,17 @@
         }
 
         synchronized (mLock) {
-            pw.println("PRINT MANAGER STATE (dumpsys print)");
-            final int userStateCount = mUserStates.size();
-            for (int i = 0; i < userStateCount; i++) {
-                UserState userState = mUserStates.get(i);
-                userState.dump(fd, pw, "");
-                pw.println();
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                pw.println("PRINT MANAGER STATE (dumpsys print)");
+                final int userStateCount = mUserStates.size();
+                for (int i = 0; i < userStateCount; i++) {
+                    UserState userState = mUserStates.get(i);
+                    userState.dump(fd, pw, "");
+                    pw.println();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
     }
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 86c68f3..d471b57 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -35,6 +35,7 @@
 import android.net.wifi.BatchedScanResult;
 import android.net.wifi.BatchedScanSettings;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.ProxySettings;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiStateMachine;
@@ -175,8 +176,19 @@
                     WifiConfiguration config = (WifiConfiguration) msg.obj;
                     int networkId = msg.arg1;
                     if (config != null && config.isValid()) {
-                        if (DBG) Slog.d(TAG, "Connect with config" + config);
-                        mWifiStateMachine.sendMessage(Message.obtain(msg));
+                        // This is restricted because there is no UI for the user to
+                        // monitor/control PAC.
+                        if (config.proxySettings != ProxySettings.PAC) {
+                            if (DBG) Slog.d(TAG, "Connect with config" + config);
+                            mWifiStateMachine.sendMessage(Message.obtain(msg));
+                        } else {
+                            Slog.e(TAG,  "ClientHandler.handleMessage cannot process msg with PAC");
+                            if (msg.what == WifiManager.CONNECT_NETWORK) {
+                                replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
+                            } else {
+                                replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
+                            }
+                        }
                     } else if (config == null
                             && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
                         if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
@@ -685,6 +697,9 @@
      */
     public int addOrUpdateNetwork(WifiConfiguration config) {
         enforceChangePermission();
+        if (config.proxySettings == ProxySettings.PAC) {
+            enforceConnectivityInternalPermission();
+        }
         if (config.isValid()) {
             if (mWifiStateMachineChannel != null) {
                 return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config);
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index afa4f78..52f2325 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -107,7 +107,7 @@
     Region mTouchExcludeRegion = new Region();
 
     /** Save allocating when retrieving tasks */
-    ArrayList<Task> mTmpTasks = new ArrayList<Task>();
+    ArrayList<Task> mTaskHistory = new ArrayList<Task>();
 
     /** Save allocating when calculating rects */
     Rect mTmpRect = new Rect();
@@ -163,7 +163,7 @@
     void moveStack(TaskStack stack, boolean toTop) {
         mStackHistory.remove(stack);
         mStackHistory.add(toTop ? mStackHistory.size() : 0, stack);
-        mService.moveStackWindowsLocked(stack);
+        mService.moveStackWindowsLocked(this);
     }
 
     public boolean isPrivate() {
@@ -175,14 +175,35 @@
      * @return All the Tasks, in order, on this display.
      */
     ArrayList<Task> getTasks() {
-        mTmpTasks.clear();
-        final int numStacks = mStackHistory.size();
-        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
+        return mTaskHistory;
+    }
+
+    void addTask(Task task, boolean toTop) {
+        mTaskHistory.remove(task);
+
+        final int userId = task.mUserId;
+        int taskNdx;
+        final int numTasks = mTaskHistory.size();
+        if (toTop) {
+            for (taskNdx = numTasks - 1; taskNdx >= 0; --taskNdx) {
+                if (mTaskHistory.get(taskNdx).mUserId == userId) {
+                    break;
+                }
+            }
+            ++taskNdx;
+        } else {
+            for (taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+                if (mTaskHistory.get(taskNdx).mUserId == userId) {
+                    break;
+                }
+            }
         }
-        if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" +
-                mStackHistory);
-        return mTmpTasks;
+
+        mTaskHistory.add(taskNdx, task);
+    }
+
+    void removeTask(Task task) {
+        mTaskHistory.remove(task);
     }
 
     TaskStack getHomeStack() {
@@ -205,10 +226,9 @@
 
     /** @return The number of tokens in all of the Tasks on this display. */
     int numTokens() {
-        getTasks();
         int count = 0;
-        for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            count += mTmpTasks.get(taskNdx).mAppTokens.size();
+        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+            count += mTaskHistory.get(taskNdx).mAppTokens.size();
         }
         return count;
     }
@@ -469,8 +489,8 @@
             pw.println();
             pw.println("  Application tokens in Z order:");
             getTasks();
-            for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
-                AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
+            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+                AppTokenList tokens = mTaskHistory.get(taskNdx).mAppTokens;
                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                     final AppWindowToken wtoken = tokens.get(tokenNdx);
                     pw.print("  App #"); pw.print(ndx--);
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 2347a19..34bef68 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -120,6 +120,7 @@
         mTasks.add(stackNdx, task);
 
         task.mStack = this;
+        mDisplayContent.addTask(task, toTop);
         return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID);
     }
 
@@ -145,6 +146,7 @@
         if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task);
         mStackBox.makeDirty();
         mTasks.remove(task);
+        mDisplayContent.removeTask(task);
     }
 
     int remove() {
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index ca87b4f..cd46bb8 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -121,12 +121,6 @@
         mDisplayContentsAnimators.delete(displayId);
     }
 
-    AppWindowAnimator getWallpaperAppAnimator() {
-        return mService.mWallpaperTarget == null
-                ? null : mService.mWallpaperTarget.mAppToken == null
-                        ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
-    }
-
     void hideWallpapersLocked(final WindowState w) {
         final WindowState wallpaperTarget = mService.mWallpaperTarget;
         final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index cfb10a0..63e09db 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -530,6 +530,7 @@
     static final long WALLPAPER_TIMEOUT = 150;
     // Time we wait after a timeout before trying to wait again.
     static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
+    boolean mAnimateWallpaperWithTarget;
 
     AppWindowToken mFocusedApp = null;
 
@@ -4732,11 +4733,9 @@
         return index;
     }
 
-    void moveStackWindowsLocked(TaskStack stack) {
-        DisplayContent displayContent = stack.getDisplayContent();
-
+    void moveStackWindowsLocked(DisplayContent displayContent) {
         // First remove all of the windows from the list.
-        final ArrayList<Task> tasks = stack.getTasks();
+        final ArrayList<Task> tasks = displayContent.getTasks();
         final int numTasks = tasks.size();
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
@@ -4812,7 +4811,7 @@
                 }
                 final TaskStack stack = task.mStack;
                 stack.moveTaskToBottom(task);
-                moveStackWindowsLocked(stack);
+                moveStackWindowsLocked(stack.getDisplayContent());
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -5723,7 +5722,7 @@
         canvas.drawBitmap(rawss, matrix, null);
         canvas.setBitmap(null);
 
-        if (true || DEBUG_SCREENSHOT) {
+        if (DEBUG_SCREENSHOT) {
             // TEST IF IT's ALL BLACK
             int[] buffer = new int[bm.getWidth() * bm.getHeight()];
             bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
@@ -7636,22 +7635,27 @@
         if (displayId != Display.DEFAULT_DISPLAY) {
             throw new IllegalArgumentException("Can only set the default display");
         }
-        synchronized(mWindowMap) {
-            // Set some sort of reasonable bounds on the size of the display that we
-            // will try to emulate.
-            final int MIN_WIDTH = 200;
-            final int MIN_HEIGHT = 200;
-            final int MAX_SCALE = 2;
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent != null) {
-                width = Math.min(Math.max(width, MIN_WIDTH),
-                        displayContent.mInitialDisplayWidth * MAX_SCALE);
-                height = Math.min(Math.max(height, MIN_HEIGHT),
-                        displayContent.mInitialDisplayHeight * MAX_SCALE);
-                setForcedDisplaySizeLocked(displayContent, width, height);
-                Settings.Global.putString(mContext.getContentResolver(),
-                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized(mWindowMap) {
+                // Set some sort of reasonable bounds on the size of the display that we
+                // will try to emulate.
+                final int MIN_WIDTH = 200;
+                final int MIN_HEIGHT = 200;
+                final int MAX_SCALE = 2;
+                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                if (displayContent != null) {
+                    width = Math.min(Math.max(width, MIN_WIDTH),
+                            displayContent.mInitialDisplayWidth * MAX_SCALE);
+                    height = Math.min(Math.max(height, MIN_HEIGHT),
+                            displayContent.mInitialDisplayHeight * MAX_SCALE);
+                    setForcedDisplaySizeLocked(displayContent, width, height);
+                    Settings.Global.putString(mContext.getContentResolver(),
+                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -7722,14 +7726,19 @@
         if (displayId != Display.DEFAULT_DISPLAY) {
             throw new IllegalArgumentException("Can only set the default display");
         }
-        synchronized(mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent != null) {
-                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
-                        displayContent.mInitialDisplayHeight);
-                Settings.Global.putString(mContext.getContentResolver(),
-                        Settings.Global.DISPLAY_SIZE_FORCED, "");
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized(mWindowMap) {
+                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                if (displayContent != null) {
+                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                            displayContent.mInitialDisplayHeight);
+                    Settings.Global.putString(mContext.getContentResolver(),
+                            Settings.Global.DISPLAY_SIZE_FORCED, "");
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -7770,13 +7779,18 @@
         if (displayId != Display.DEFAULT_DISPLAY) {
             throw new IllegalArgumentException("Can only set the default display");
         }
-        synchronized(mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent != null) {
-                setForcedDisplayDensityLocked(displayContent, density);
-                Settings.Global.putString(mContext.getContentResolver(),
-                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized(mWindowMap) {
+                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                if (displayContent != null) {
+                    setForcedDisplayDensityLocked(displayContent, density);
+                    Settings.Global.putString(mContext.getContentResolver(),
+                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -7801,13 +7815,19 @@
         if (displayId != Display.DEFAULT_DISPLAY) {
             throw new IllegalArgumentException("Can only set the default display");
         }
-        synchronized(mWindowMap) {
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent != null) {
-                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
-                Settings.Global.putString(mContext.getContentResolver(),
-                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized(mWindowMap) {
+                final DisplayContent displayContent = getDisplayContentLocked(displayId);
+                if (displayContent != null) {
+                    setForcedDisplayDensityLocked(displayContent,
+                            displayContent.mInitialDisplayDensity);
+                    Settings.Global.putString(mContext.getContentResolver(),
+                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -7855,11 +7875,16 @@
             throw new SecurityException("Must hold permission " +
                     android.Manifest.permission.WRITE_SECURE_SETTINGS);
         }
-        synchronized(mWindowMap) {
-            DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent != null) {
-                setOverscanLocked(displayContent, left, top, right, bottom);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized(mWindowMap) {
+                DisplayContent displayContent = getDisplayContentLocked(displayId);
+                if (displayContent != null) {
+                    setOverscanLocked(displayContent, left, top, right, bottom);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -8476,6 +8501,7 @@
                 }
             }
 
+            mAnimateWallpaperWithTarget = false;
             if (closingAppHasWallpaper && openingAppHasWallpaper) {
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
                 switch (transit) {
@@ -8491,7 +8517,8 @@
                         break;
                 }
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
-            } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
+            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
+                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
                 // We are transitioning from an activity with
                 // a wallpaper to one without.
                 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
@@ -8503,6 +8530,8 @@
                 transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "New transit into wallpaper: " + transit);
+            } else {
+                mAnimateWallpaperWithTarget = true;
             }
 
             // If all closing windows are obscured, then there is
@@ -8558,8 +8587,7 @@
                 wtoken.mAppAnimator.clearThumbnail();
                 wtoken.inPendingTransaction = false;
                 wtoken.mAppAnimator.animation = null;
-                setTokenVisibilityLocked(wtoken, animLp, false,
-                        transit, false);
+                setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToHide = false;
                 // Force the allDrawn flag, because we want to start
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index e2fae89..af00d83 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -845,9 +845,9 @@
 
         // Wallpapers are animated based on the "real" window they
         // are currently targeting.
-        if (mIsWallpaper && mService.mLowerWallpaperTarget == null
-                && mService.mWallpaperTarget != null) {
-            final WindowStateAnimator wallpaperAnimator = mService.mWallpaperTarget.mWinAnimator;
+        final WindowState wallpaperTarget = mService.mWallpaperTarget;
+        if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
+            final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
             if (wallpaperAnimator.mHasLocalTransformation &&
                     wallpaperAnimator.mAnimation != null &&
                     !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
@@ -856,8 +856,9 @@
                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
                 }
             }
-            final AppWindowAnimator wpAppAnimator = mAnimator.getWallpaperAppAnimator();
-            if (wpAppAnimator != null && wpAppAnimator.hasTransformation
+            final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ?
+                    null : wallpaperTarget.mAppToken.mAppAnimator;
+                if (wpAppAnimator != null && wpAppAnimator.hasTransformation
                     && wpAppAnimator.animation != null
                     && !wpAppAnimator.animation.getDetachWallpaper()) {
                 appTransformation = wpAppAnimator.transformation;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 6c4bd66..606fcb4 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -693,7 +693,7 @@
         mOperatorNumeric = m.getString("operator-numeric");
         mIsManualNetworkSelection = m.getBoolean("manual");
         mRilVoiceRadioTechnology = m.getInt("radioTechnology");
-        mRilVoiceRadioTechnology = m.getInt("dataRadioTechnology");
+        mRilDataRadioTechnology = m.getInt("dataRadioTechnology");
         mCssIndicator = m.getBoolean("cssIndicator");
         mNetworkId = m.getInt("networkId");
         mSystemId = m.getInt("systemId");
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index e3c664b..f6143ed 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -581,6 +581,10 @@
         return countryIso;
     }
 
+    protected static String getCurrentCountryIso(Context context) {
+        return getCurrentCountryIso(context, Locale.getDefault());
+    }
+
     /**
      * @return a string debug representation of this instance.
      */
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index dd5f644..c63be91 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.database.SQLException;
-import android.location.CountryDetector;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -271,11 +270,9 @@
 
                     // Use the number entered by the user for display.
                     if (!TextUtils.isEmpty(cw.number)) {
-                        CountryDetector detector = (CountryDetector) mQueryContext.getSystemService(
-                                Context.COUNTRY_DETECTOR);
                         mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number,
                                 mCallerInfo.normalizedNumber,
-                                detector.detectCountry().getCountryIso());
+                                CallerInfo.getCurrentCountryIso(mQueryContext));
                     }
                 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 584411b..7bd2c84 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -155,6 +155,26 @@
     boolean supplyPuk(String puk, String pin);
 
     /**
+     * Supply a pin to unlock the SIM.  Blocks until a result is determined.
+     * Returns a specific success/error code.
+     * @param pin The pin to check.
+     * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
+     *         retValue[1] = number of attempts remaining if known otherwise -1
+     */
+    int[] supplyPinReportResult(String pin);
+
+    /**
+     * Supply puk to unlock the SIM and set SIM pin to new pin.
+     * Blocks until a result is determined.
+     * Returns a specific success/error code
+     * @param puk The puk to check
+     *        pin The pin to check.
+     * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
+     *         retValue[1] = number of attempts remaining if known otherwise -1
+     */
+    int[] supplyPukReportResult(String puk, String pin);
+
+    /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
      * without SEND (so <code>dial</code> is not appropriate).
      *
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 4a4a62b..4163255 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -86,6 +86,14 @@
     public static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged";
 
     /**
+     * Return codes for supplyPinReturnResult and
+     * supplyPukReturnResult APIs
+     */
+    public static final int PIN_RESULT_SUCCESS = 0;
+    public static final int PIN_PASSWORD_INCORRECT = 1;
+    public static final int PIN_GENERAL_FAILURE = 2;
+
+    /**
      * Return codes for <code>enableApnType()</code>
      */
     public static final int APN_ALREADY_ACTIVE     = 0;
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 3797b49..d8e113a 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -2487,6 +2487,15 @@
                 continue;
             }
 
+            // Get the preferred density if there is one. We do not match exactly for density.
+            // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
+            // pick xhdpi.
+            uint32_t preferredDensity = 0;
+            const SortedVector<uint32_t>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
+            if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
+                preferredDensity = (*preferredConfigs)[0];
+            }
+
             // Now deal with preferred configurations.
             for (int axis=AXIS_START; axis<=AXIS_END; axis++) {
                 for (size_t k=0; k<grp->getFiles().size(); k++) {
@@ -2512,12 +2521,30 @@
                         // This is a resource we would prefer not to have.  Check
                         // to see if have a similar variation that we would like
                         // to have and, if so, we can drop it.
+
+                        uint32_t bestDensity = config.density;
+
                         for (size_t m=0; m<grp->getFiles().size(); m++) {
                             if (m == k) continue;
                             sp<AaptFile> mfile = grp->getFiles().valueAt(m);
                             const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
                             if (AaptGroupEntry::configSameExcept(config, mconfig, axis)) {
-                                if (prefFilter.match(axis, mconfig)) {
+                                if (axis == AXIS_DENSITY && preferredDensity > 0) {
+                                    // See if there is a better density resource
+                                    if (mconfig.density < bestDensity &&
+                                            mconfig.density > preferredDensity &&
+                                            bestDensity > preferredDensity) {
+                                        // This density is between our best density and
+                                        // the preferred density, therefore it is better.
+                                        bestDensity = mconfig.density;
+                                    } else if (mconfig.density > bestDensity &&
+                                            bestDensity < preferredDensity) {
+                                        // This density is better than our best density and
+                                        // our best density was smaller than our preferred
+                                        // density, so it is better.
+                                        bestDensity = mconfig.density;
+                                    }
+                                } else if (prefFilter.match(axis, mconfig)) {
                                     if (bundle->getVerbose()) {
                                         printf("Pruning unneeded resource: %s\n",
                                                 file->getPrintableSource().string());
@@ -2528,6 +2555,16 @@
                                 }
                             }
                         }
+
+                        if (axis == AXIS_DENSITY && preferredDensity > 0 &&
+                                bestDensity != config.density) {
+                            if (bundle->getVerbose()) {
+                                printf("Pruning unneeded resource: %s\n",
+                                        file->getPrintableSource().string());
+                            }
+                            grp->removeFile(k);
+                            k--;
+                        }
                     }
                 }
             }
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index be27b54..fa68796 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -48,6 +48,11 @@
  */
 public final class NinePatch_Delegate {
 
+    // ---- delegate manager ----
+    private static final DelegateManager<NinePatch_Delegate> sManager =
+            new DelegateManager<NinePatch_Delegate>(NinePatch_Delegate.class);
+
+    // ---- delegate helper data ----
     /**
      * Cache map for {@link NinePatchChunk}.
      * When the chunks are created they are serialized into a byte[], and both are put
@@ -60,6 +65,10 @@
     private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache =
         new HashMap<byte[], SoftReference<NinePatchChunk>>();
 
+    // ---- delegate data ----
+    private byte[] chunk;
+
+
     // ---- Public Helper methods ----
 
     /**
@@ -149,32 +158,39 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void validateNinePatchChunk(int bitmap, byte[] chunk) {
+    /*package*/ static int validateNinePatchChunk(int bitmap, byte[] chunk) {
         // the default JNI implementation only checks that the byte[] has the same
         // size as the C struct it represent. Since we cannot do the same check (serialization
         // will return different size depending on content), we do nothing.
+        NinePatch_Delegate newDelegate = new NinePatch_Delegate();
+        newDelegate.chunk = chunk;
+        return sManager.addNewDelegate(newDelegate);
+    }
+
+    /*package*/ static void nativeFinalize(int chunk) {
+        sManager.removeJavaReferenceFor(chunk);
     }
 
     @LayoutlibDelegate
     /*package*/ static void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
-            byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) {
+            int chunk, int paint_instance_or_null, int destDensity, int srcDensity) {
         draw(canvas_instance,
                 (int) loc.left, (int) loc.top, (int) loc.width(), (int) loc.height(),
-                bitmap_instance, c, paint_instance_or_null,
+                bitmap_instance, chunk, paint_instance_or_null,
                 destDensity, srcDensity);
     }
 
     @LayoutlibDelegate
     /*package*/ static void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
-            byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) {
+            int chunk, int paint_instance_or_null, int destDensity, int srcDensity) {
         draw(canvas_instance,
                 loc.left, loc.top, loc.width(), loc.height(),
-                bitmap_instance, c, paint_instance_or_null,
+                bitmap_instance, chunk, paint_instance_or_null,
                 destDensity, srcDensity);
     }
 
     @LayoutlibDelegate
-    /*package*/ static int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location) {
+    /*package*/ static int nativeGetTransparentRegion(int bitmap, int chunk, Rect location) {
         return 0;
     }
 
@@ -182,7 +198,7 @@
 
     private static void draw(int canvas_instance,
             final int left, final int top, final int right, final int bottom,
-            int bitmap_instance, byte[] c, int paint_instance_or_null,
+            int bitmap_instance, int chunk, int paint_instance_or_null,
             final int destDensity, final int srcDensity) {
         // get the delegate from the native int.
         final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
@@ -190,6 +206,11 @@
             return;
         }
 
+        byte[] c = null;
+        NinePatch_Delegate delegate = sManager.getDelegate(chunk);
+        if (delegate != null) {
+            c = delegate.chunk;
+        }
         if (c == null) {
             // not a 9-patch?
             BufferedImage image = bitmap_delegate.getImage();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index a8b58aa..281337c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -81,6 +81,11 @@
     }
 
     @Override
+    public void updateWakeLockUids(IBinder arg0, int[] arg1) throws RemoteException {
+        // pass for now.
+    }
+
+    @Override
     public void setAttentionLight(boolean arg0, int arg1) throws RemoteException {
         // pass for now.
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
index 9a633bf..7e5ae8d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
@@ -17,6 +17,7 @@
 
 import android.util.DisplayMetrics;
 import android.view.Display;
+import android.view.DisplayAdjustments;
 import android.view.DisplayInfo;
 import android.view.View;
 import android.view.WindowManager;
@@ -32,7 +33,8 @@
         DisplayInfo info = new DisplayInfo();
         info.logicalHeight = mMetrics.heightPixels;
         info.logicalWidth = mMetrics.widthPixels;
-        mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, null);
+        mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info,
+                DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 87047b3..23d08e3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -248,11 +248,16 @@
      * The counterpart is {@link #setUp()}.
      */
     private void tearDown() {
-        // Make sure to remove static references, otherwise we could not unload the lib
-        mContext.disposeResources();
+        // The context may be null, if there was an error during init().
+        if (mContext != null) {
+            // Make sure to remove static references, otherwise we could not unload the lib
+            mContext.disposeResources();
+        }
 
-        // quit HandlerThread created during this session.
-        HandlerThread_Delegate.cleanUp(sCurrentContext);
+        if (sCurrentContext != null) {
+            // quit HandlerThread created during this session.
+            HandlerThread_Delegate.cleanUp(sCurrentContext);
+        }
 
         // clear the stored ViewConfiguration since the map is per density and not per context.
         ViewConfiguration_Accessor.clearConfigurations();
@@ -263,8 +268,12 @@
         sCurrentContext = null;
 
         Bridge.setLog(null);
-        mContext.getRenderResources().setFrameworkResourceIdProvider(null);
-        mContext.getRenderResources().setLogger(null);
+        if (mContext != null) {
+            mContext.getRenderResources().setFrameworkResourceIdProvider(null);
+            mContext.getRenderResources().setLogger(null);
+        }
+
+        mContext = null;
     }
 
     public static BridgeContext getCurrentContext() {
diff --git a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
new file mode 100644
index 0000000..a773d93
--- /dev/null
+++ b/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
@@ -0,0 +1,70 @@
+/*
+ * 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 libcore.icu;
+
+import java.text.FieldPosition;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.ibm.icu.text.DateIntervalFormat;
+import com.ibm.icu.util.DateInterval;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+
+public class DateIntervalFormat_Delegate {
+
+    // ---- delegate manager ----
+    private static final DelegateManager<DateIntervalFormat_Delegate> sManager =
+            new DelegateManager<DateIntervalFormat_Delegate>(DateIntervalFormat_Delegate.class);
+
+    // ---- delegate data ----
+    private DateIntervalFormat mFormat;
+
+
+    // ---- native methods ----
+
+    /*package*/static String formatDateInterval(long address, long fromDate, long toDate) {
+        DateIntervalFormat_Delegate delegate = sManager.getDelegate((int)address);
+        if (delegate == null) {
+            Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                    "Unable for find native DateIntervalFormat", null);
+            return null;
+        }
+        DateInterval interval = new DateInterval(fromDate, toDate);
+        StringBuffer sb = new StringBuffer();
+        FieldPosition pos = new FieldPosition(0);
+        delegate.mFormat.format(interval, sb, pos);
+        return sb.toString();
+    }
+
+    /*package*/ static long createDateIntervalFormat(String skeleton, String localeName,
+            String tzName) {
+        TimeZone prevDefaultTz = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone(tzName));
+        DateIntervalFormat_Delegate newDelegate = new DateIntervalFormat_Delegate();
+        newDelegate.mFormat =
+                DateIntervalFormat.getInstance(skeleton, new ULocale(localeName));
+        TimeZone.setDefault(prevDefaultTz);
+        return sManager.addNewDelegate(newDelegate);
+    }
+
+    /*package*/ static void destroyDateIntervalFormat(long address) {
+        sManager.removeJavaReferenceFor((int)address);
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index 294d743..06ae804 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -17,6 +17,8 @@
 package libcore.icu;
 
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import com.ibm.icu.text.DateTimePatternGenerator;
+import com.ibm.icu.util.ULocale;
 
 import java.util.Locale;
 
@@ -45,7 +47,8 @@
 
     @LayoutlibDelegate
     /*package*/ static String getBestDateTimePattern(String skeleton, String localeName) {
-        return "";            // TODO: check what the right value should be.
+        return DateTimePatternGenerator.getInstance(new ULocale(localeName))
+                .getBestPattern(skeleton);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 72fc932..ef2b185 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -169,9 +169,9 @@
   their return value.
 - CreateInfo class, which configured the generator. Not used yet, but could
   in theory help us track what the generator changed.
-- AutoCloseable is part of Java 7. To enable us to still run on Java 6, a new class is
-  injected. The implementation for the class has been taken from Android's libcore
-  (platform/libcore/luni/src/main/java/java/lang/AutoCloseable.java).
+- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new
+  classes are injected. The implementation for these classes has been taken from
+  Android's libcore (platform/libcore/luni/src/main/java/java/...).
 - Charsets, IntegralToString and UnsafeByteSequence are not part of the standard JAVA VM.
   They are added to the Dalvik VM for performance reasons. An implementation that is very
   close to the original (which is at platform/libcore/luni/src/main/java/...) is injected.
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 7099a4b..f6779e3 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
@@ -20,6 +20,7 @@
 import com.android.tools.layoutlib.java.AutoCloseable;
 import com.android.tools.layoutlib.java.Charsets;
 import com.android.tools.layoutlib.java.IntegralToString;
+import com.android.tools.layoutlib.java.Objects;
 import com.android.tools.layoutlib.java.UnsafeByteSequence;
 
 /**
@@ -111,6 +112,7 @@
             LayoutlibDelegate.class,
             /* Java package classes */
             AutoCloseable.class,
+            Objects.class,
             IntegralToString.class,
             UnsafeByteSequence.class,
             Charsets.class,
@@ -188,6 +190,7 @@
         "android.text.AndroidBidi",
         "android.util.FloatMath",
         "android.view.Display",
+        "libcore.icu.DateIntervalFormat",
         "libcore.icu.ICU",
     };
 
@@ -221,6 +224,7 @@
     private final static String[] JAVA_PKG_CLASSES =
         new String[] {
             "java.lang.AutoCloseable",                         "com.android.tools.layoutlib.java.AutoCloseable",
+            "java.util.Objects",                               "com.android.tools.layoutlib.java.Objects",
             "java.nio.charset.Charsets",                       "com.android.tools.layoutlib.java.Charsets",
             "java.lang.IntegralToString",                      "com.android.tools.layoutlib.java.IntegralToString",
             "java.lang.UnsafeByteSequence",                    "com.android.tools.layoutlib.java.UnsafeByteSequence",
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/java/Objects.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/Objects.java
new file mode 100644
index 0000000..eb1ef72
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/Objects.java
@@ -0,0 +1,132 @@
+/*
+ * 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 com.android.tools.layoutlib.java;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Defines the same class as the java.util.Objects which is added in Java 7.
+ * This hack makes it possible to run the Android code which uses Java 7 features
+ * (API 18 and beyond) to run on Java 6.
+ * <p/>
+ * Extracted from API level 19, file:
+ * platform/libcore/luni/src/main/java/java/util/Objects.java
+ */
+public final class Objects {
+  private Objects() {}
+
+  /**
+   * Returns 0 if {@code a == b}, or {@code c.compare(a, b)} otherwise.
+   * That is, this makes {@code c} null-safe.
+   */
+  public static <T> int compare(T a, T b, Comparator<? super T> c) {
+    if (a == b) {
+      return 0;
+    }
+    return c.compare(a, b);
+  }
+
+  /**
+   * Returns true if both arguments are null,
+   * the result of {@link Arrays#equals} if both arguments are primitive arrays,
+   * the result of {@link Arrays#deepEquals} if both arguments are arrays of reference types,
+   * and the result of {@link #equals} otherwise.
+   */
+  public static boolean deepEquals(Object a, Object b) {
+    if (a == null || b == null) {
+      return a == b;
+    } else if (a instanceof Object[] && b instanceof Object[]) {
+      return Arrays.deepEquals((Object[]) a, (Object[]) b);
+    } else if (a instanceof boolean[] && b instanceof boolean[]) {
+      return Arrays.equals((boolean[]) a, (boolean[]) b);
+    } else if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[]) a, (byte[]) b);
+    } else if (a instanceof char[] && b instanceof char[]) {
+      return Arrays.equals((char[]) a, (char[]) b);
+    } else if (a instanceof double[] && b instanceof double[]) {
+      return Arrays.equals((double[]) a, (double[]) b);
+    } else if (a instanceof float[] && b instanceof float[]) {
+      return Arrays.equals((float[]) a, (float[]) b);
+    } else if (a instanceof int[] && b instanceof int[]) {
+      return Arrays.equals((int[]) a, (int[]) b);
+    } else if (a instanceof long[] && b instanceof long[]) {
+      return Arrays.equals((long[]) a, (long[]) b);
+    } else if (a instanceof short[] && b instanceof short[]) {
+      return Arrays.equals((short[]) a, (short[]) b);
+    }
+    return a.equals(b);
+  }
+
+  /**
+   * Null-safe equivalent of {@code a.equals(b)}.
+   */
+  public static boolean equals(Object a, Object b) {
+    return (a == null) ? (b == null) : a.equals(b);
+  }
+
+  /**
+   * Convenience wrapper for {@link Arrays#hashCode}, adding varargs.
+   * This can be used to compute a hash code for an object's fields as follows:
+   * {@code Objects.hash(a, b, c)}.
+   */
+  public static int hash(Object... values) {
+    return Arrays.hashCode(values);
+  }
+
+  /**
+   * Returns 0 for null or {@code o.hashCode()}.
+   */
+  public static int hashCode(Object o) {
+    return (o == null) ? 0 : o.hashCode();
+  }
+
+  /**
+   * Returns {@code o} if non-null, or throws {@code NullPointerException}.
+   */
+  public static <T> T requireNonNull(T o) {
+    if (o == null) {
+      throw new NullPointerException();
+    }
+    return o;
+  }
+
+  /**
+   * Returns {@code o} if non-null, or throws {@code NullPointerException}
+   * with the given detail message.
+   */
+  public static <T> T requireNonNull(T o, String message) {
+    if (o == null) {
+      throw new NullPointerException(message);
+    }
+    return o;
+  }
+
+  /**
+   * Returns "null" for null or {@code o.toString()}.
+   */
+  public static String toString(Object o) {
+    return (o == null) ? "null" : o.toString();
+  }
+
+  /**
+   * Returns {@code nullString} for null or {@code o.toString()}.
+   */
+  public static String toString(Object o, String nullString) {
+    return (o == null) ? nullString : o.toString();
+  }
+}
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 4bc3dda..78da7e7 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -89,6 +89,7 @@
 import java.net.Inet6Address;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.Iterator;
@@ -500,6 +501,10 @@
     // until after, so the write is deferred
     private volatile String mPersistedCountryCode;
 
+    // Supplicant doesn't like setting the same country code multiple times (it may drop
+    // currently connected network), so we save the country code here to avoid redundency
+    private String mLastSetCountryCode;
+
     private static final int MIN_RSSI = -200;
     private static final int MAX_RSSI = 256;
 
@@ -3022,8 +3027,16 @@
                 case CMD_SET_COUNTRY_CODE:
                     String country = (String) message.obj;
                     if (DBG) log("set country code " + country);
-                    if (!mWifiNative.setCountryCode(country)) {
-                        loge("Failed to set country code " + country);
+                    if (country != null) {
+                        country = country.toUpperCase(Locale.ROOT);
+                        if (mLastSetCountryCode == null
+                                || country.equals(mLastSetCountryCode) == false) {
+                            if (mWifiNative.setCountryCode(country)) {
+                                mLastSetCountryCode = country;
+                            } else {
+                                loge("Failed to set country code " + country);
+                            }
+                        }
                     }
                     break;
                 case CMD_SET_FREQUENCY_BAND:
@@ -3156,6 +3169,8 @@
             intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
             noteScanEnd(); // wrap up any pending request.
+
+            mLastSetCountryCode = null;
         }
     }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 625ffb8..8b07208 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -85,6 +85,8 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
+
 
 /**
  * WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications
@@ -201,6 +203,10 @@
      */
     private boolean mDiscoveryBlocked;
 
+    // Supplicant doesn't like setting the same country code multiple times (it may drop
+    // current connected network), so we save the country code here to avoid redundency
+    private String mLastSetCountryCode;
+
     /*
      * remember if we were in a scan when it had to be stopped
      */
@@ -1070,7 +1076,13 @@
                     break;
                 case SET_COUNTRY_CODE:
                     String countryCode = (String) message.obj;
-                    mWifiNative.setCountryCode(countryCode);
+                    countryCode = countryCode.toUpperCase(Locale.ROOT);
+                    if (mLastSetCountryCode == null ||
+                            countryCode.equals(mLastSetCountryCode) == false) {
+                        if (mWifiNative.setCountryCode(countryCode)) {
+                            mLastSetCountryCode = countryCode;
+                        }
+                    }
                     break;
                 default:
                    return NOT_HANDLED;
@@ -1082,6 +1094,8 @@
         public void exit() {
             sendP2pStateChangedBroadcast(false);
             mNetworkInfo.setIsAvailable(false);
+
+            mLastSetCountryCode = null;
         }
     }