Merge "Switch to the new Skia PDF generation APIs." into klp-dev
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index bb04063..7ca3459 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2272,9 +2272,12 @@
     public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
         FileOutputStream fout = new FileOutputStream(fd);
         PrintWriter pw = new FastPrintWriter(fout);
-        dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName });
+        dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] {
+                "-a", "package", packageName });
         pw.println();
-        dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { packageName });
+        dumpService(pw, fd, "meminfo", new String[] { "--local", packageName });
+        pw.println();
+        dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { "-a", packageName });
         pw.println();
         dumpService(pw, fd, "usagestats", new String[] { "--packages", packageName });
         pw.println();
@@ -2296,7 +2299,7 @@
             pw.flush();
             tp = new TransferPipe();
             tp.setBufferPrefix("  ");
-            service.dump(tp.getWriteFd().getFileDescriptor(), args);
+            service.dumpAsync(tp.getWriteFd().getFileDescriptor(), args);
             tp.go(fd);
         } catch (Throwable e) {
             if (tp != null) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7ae8ca8..9ada6e6 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -106,6 +106,11 @@
     public static final int FOREGROUND_ACTIVITY = 10;
 
     /**
+     * A constant indicating a wifi batched scan is active
+     */
+    public static final int WIFI_BATCHED_SCAN = 11;
+
+    /**
      * Include all of the data in the stats, including previously saved data.
      */
     public static final int STATS_SINCE_CHARGED = 0;
@@ -270,6 +275,8 @@
         public abstract void noteFullWifiLockReleasedLocked();
         public abstract void noteWifiScanStartedLocked();
         public abstract void noteWifiScanStoppedLocked();
+        public abstract void noteWifiBatchedScanStartedLocked(int csph);
+        public abstract void noteWifiBatchedScanStoppedLocked();
         public abstract void noteWifiMulticastEnabledLocked();
         public abstract void noteWifiMulticastDisabledLocked();
         public abstract void noteAudioTurnedOnLocked();
@@ -281,6 +288,7 @@
         public abstract long getWifiRunningTime(long batteryRealtime, int which);
         public abstract long getFullWifiLockTime(long batteryRealtime, int which);
         public abstract long getWifiScanTime(long batteryRealtime, int which);
+        public abstract long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which);
         public abstract long getWifiMulticastTime(long batteryRealtime,
                                                   int which);
         public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
@@ -288,6 +296,8 @@
         public abstract Timer getForegroundActivityTimer();
         public abstract Timer getVibratorOnTimer();
 
+        public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5;
+
         /**
          * Note that these must match the constants in android.os.PowerManager.
          * Also, if the user activity types change, the BatteryStatsImpl.VERSION must
@@ -2081,9 +2091,11 @@
                                         TimeUtils.formatDuration(ew.usedTime, pw);
                                         pw.print(" over ");
                                         TimeUtils.formatDuration(ew.overTime, pw);
-                                        pw.print(" (");
-                                        pw.print((ew.usedTime*100)/ew.overTime);
-                                        pw.println("%)");
+                                        if (ew.overTime != 0) {
+                                            pw.print(" (");
+                                            pw.print((ew.usedTime*100)/ew.overTime);
+                                            pw.println("%)");
+                                        }
                             }
                         }
                         uidActivity = true;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 525517c..43c4b49 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -68,6 +68,8 @@
     void noteFullWifiLockReleasedFromSource(in WorkSource ws);
     void noteWifiScanStartedFromSource(in WorkSource ws);
     void noteWifiScanStoppedFromSource(in WorkSource ws);
+    void noteWifiBatchedScanStartedFromSource(in WorkSource ws, int csph);
+    void noteWifiBatchedScanStoppedFromSource(in WorkSource ws);
     void noteWifiMulticastEnabledFromSource(in WorkSource ws);
     void noteWifiMulticastDisabledFromSource(in WorkSource ws);
     void noteNetworkInterfaceType(String iface, int type);
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 20b8c95..0cad33c 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -1758,21 +1758,34 @@
                 mStartTime, now);
         ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
         boolean printedHeader = false;
+        boolean sepNeeded = false;
         for (int ip=0; ip<pkgMap.size(); ip++) {
-            String pkgName = pkgMap.keyAt(ip);
-            if (reqPackage != null && !reqPackage.equals(pkgName)) {
-                continue;
-            }
-            SparseArray<PackageState> uids = pkgMap.valueAt(ip);
+            final String pkgName = pkgMap.keyAt(ip);
+            final SparseArray<PackageState> uids = pkgMap.valueAt(ip);
             for (int iu=0; iu<uids.size(); iu++) {
-                int uid = uids.keyAt(iu);
-                PackageState pkgState = uids.valueAt(iu);
+                final int uid = uids.keyAt(iu);
+                final PackageState pkgState = uids.valueAt(iu);
                 final int NPROCS = pkgState.mProcesses.size();
                 final int NSRVS = pkgState.mServices.size();
+                final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
+                if (!pkgMatch) {
+                    boolean procMatch = false;
+                    for (int iproc=0; iproc<NPROCS; iproc++) {
+                        ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                        if (reqPackage.equals(proc.mName)) {
+                            procMatch = true;
+                            break;
+                        }
+                    }
+                    if (!procMatch) {
+                        continue;
+                    }
+                }
                 if (NPROCS > 0 || NSRVS > 0) {
                     if (!printedHeader) {
                         pw.println("Per-Package Stats:");
                         printedHeader = true;
+                        sepNeeded = true;
                     }
                     pw.print("  * "); pw.print(pkgName); pw.print(" / ");
                             UserHandle.formatUid(pw, uid); pw.println(":");
@@ -1780,6 +1793,9 @@
                 if (!dumpSummary || dumpAll) {
                     for (int iproc=0; iproc<NPROCS; iproc++) {
                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                        if (!pkgMatch && !reqPackage.equals(proc.mName)) {
+                            continue;
+                        }
                         if (activeOnly && !proc.isInUse()) {
                             pw.print("      (Not active: ");
                                     pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
@@ -1787,7 +1803,11 @@
                         }
                         pw.print("      Process ");
                         pw.print(pkgState.mProcesses.keyAt(iproc));
-                        pw.print(" (");
+                        if (proc.mCommonProcess.mMultiPackage) {
+                            pw.print(" (multi, ");
+                        } else {
+                            pw.print(" (unique, ");
+                        }
                         pw.print(proc.mDurationsTableSize);
                         pw.print(" entries)");
                         pw.println(":");
@@ -1801,6 +1821,9 @@
                     ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
                     for (int iproc=0; iproc<NPROCS; iproc++) {
                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                        if (!pkgMatch && !reqPackage.equals(proc.mName)) {
+                            continue;
+                        }
                         if (activeOnly && !proc.isInUse()) {
                             continue;
                         }
@@ -1811,6 +1834,9 @@
                 }
                 for (int isvc=0; isvc<NSRVS; isvc++) {
                     ServiceState svc = pkgState.mServices.valueAt(isvc);
+                    if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) {
+                        continue;
+                    }
                     if (activeOnly && !svc.isInUse()) {
                         pw.print("      (Not active: ");
                                 pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
@@ -1840,64 +1866,73 @@
                         if (svc.mOwner != null) {
                             pw.print("        mOwner="); pw.println(svc.mOwner);
                         }
+                        if (svc.mStarted || svc.mRestarting) {
+                            pw.print("        mStarted="); pw.print(svc.mStarted);
+                            pw.print(" mRestarting="); pw.println(svc.mRestarting);
+                        }
                     }
                 }
             }
         }
 
-        if (reqPackage == null) {
-            ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
-            printedHeader = false;
-            int numShownProcs = 0, numTotalProcs = 0;
-            for (int ip=0; ip<procMap.size(); ip++) {
-                String procName = procMap.keyAt(ip);
-                SparseArray<ProcessState> uids = procMap.valueAt(ip);
-                for (int iu=0; iu<uids.size(); iu++) {
-                    int uid = uids.keyAt(iu);
-                    numTotalProcs++;
-                    ProcessState proc = uids.valueAt(iu);
-                    if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
-                            && proc.mPssTableSize == 0) {
-                        continue;
-                    }
-                    numShownProcs++;
-                    if (!printedHeader) {
-                        pw.println();
-                        pw.println("Per-Process Stats:");
-                        printedHeader = true;
-                    }
-                    if (activeOnly && !proc.isInUse()) {
-                        pw.print("      (Not active: "); pw.print(procName); pw.println(")");
-                        continue;
-                    }
-                    pw.print("  * "); pw.print(procName); pw.print(" / ");
-                            UserHandle.formatUid(pw, uid);
-                            pw.print(" ("); pw.print(proc.mDurationsTableSize);
-                            pw.print(" entries)"); pw.println(":");
-                    dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                            ALL_PROC_STATES, now);
-                    dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                            ALL_PROC_STATES);
-                    if (dumpAll) {
-                        dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
-                    }
+        ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+        printedHeader = false;
+        int numShownProcs = 0, numTotalProcs = 0;
+        for (int ip=0; ip<procMap.size(); ip++) {
+            String procName = procMap.keyAt(ip);
+            SparseArray<ProcessState> uids = procMap.valueAt(ip);
+            for (int iu=0; iu<uids.size(); iu++) {
+                int uid = uids.keyAt(iu);
+                numTotalProcs++;
+                ProcessState proc = uids.valueAt(iu);
+                if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
+                        && proc.mPssTableSize == 0) {
+                    continue;
                 }
+                if (!proc.mMultiPackage) {
+                    continue;
+                }
+                if (reqPackage != null && !reqPackage.equals(procName)
+                        && !reqPackage.equals(proc.mPackage)) {
+                    continue;
+                }
+                numShownProcs++;
+                if (sepNeeded) {
+                    pw.println();
+                }
+                sepNeeded = true;
+                if (!printedHeader) {
+                    pw.println("Multi-Package Common Processes:");
+                    printedHeader = true;
+                }
+                if (activeOnly && !proc.isInUse()) {
+                    pw.print("      (Not active: "); pw.print(procName); pw.println(")");
+                    continue;
+                }
+                pw.print("  * "); pw.print(procName); pw.print(" / ");
+                        UserHandle.formatUid(pw, uid);
+                        pw.print(" ("); pw.print(proc.mDurationsTableSize);
+                        pw.print(" entries)"); pw.println(":");
+                dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+                        ALL_PROC_STATES, now);
+                dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+                        ALL_PROC_STATES);
+                dumpProcessInternalLocked(pw, "        ", proc, dumpAll);
             }
-            if (dumpAll) {
-                pw.println();
-                pw.print("  Total procs: "); pw.print(numShownProcs);
-                        pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
-            }
+        }
+        if (dumpAll) {
+            pw.println();
+            pw.print("  Total procs: "); pw.print(numShownProcs);
+                    pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
+        }
 
+        if (sepNeeded) {
             pw.println();
-            if (dumpSummary) {
-                pw.println("Summary:");
-                dumpSummaryLocked(pw, reqPackage, now, activeOnly);
-            } else {
-                dumpTotalsLocked(pw, now);
-            }
+        }
+        if (dumpSummary) {
+            pw.println("Summary:");
+            dumpSummaryLocked(pw, reqPackage, now, activeOnly);
         } else {
-            pw.println();
             dumpTotalsLocked(pw, now);
         }
 
@@ -2031,17 +2066,20 @@
     public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
             int[] procStates, int sortProcStates[], long now, String reqPackage,
             boolean activeOnly) {
-        ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
-        ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
+        final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
+        final ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
         for (int ip=0; ip<pkgMap.size(); ip++) {
-            if (reqPackage != null && !reqPackage.equals(pkgMap.keyAt(ip))) {
-                continue;
-            }
-            SparseArray<PackageState> procs = pkgMap.valueAt(ip);
+            final String pkgName = pkgMap.keyAt(ip);
+            final SparseArray<PackageState> procs = pkgMap.valueAt(ip);
             for (int iu=0; iu<procs.size(); iu++) {
-                PackageState state = procs.valueAt(iu);
-                for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
-                    ProcessState proc = state.mProcesses.valueAt(iproc);
+                final PackageState state = procs.valueAt(iu);
+                final int NPROCS = state.mProcesses.size();
+                final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName);
+                for (int iproc=0; iproc<NPROCS; iproc++) {
+                    final ProcessState proc = state.mProcesses.valueAt(iproc);
+                    if (!pkgMatch && !reqPackage.equals(proc.mName)) {
+                        continue;
+                    }
                     if (activeOnly && !proc.isInUse()) {
                         continue;
                     }
@@ -2601,23 +2639,35 @@
             }
         }
 
-        void incStartedServices(int memFactor, long now) {
+        void incStartedServices(int memFactor, long now, String serviceName) {
+            if (false) {
+                RuntimeException here = new RuntimeException("here");
+                here.fillInStackTrace();
+                Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
+                        + " to " + (mNumStartedServices+1), here);
+            }
             if (mCommonProcess != this) {
-                mCommonProcess.incStartedServices(memFactor, now);
+                mCommonProcess.incStartedServices(memFactor, now, serviceName);
             }
             mNumStartedServices++;
             if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) {
-                setState(STATE_NOTHING, memFactor, now, null);
+                setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now);
             }
         }
 
-        void decStartedServices(int memFactor, long now) {
+        void decStartedServices(int memFactor, long now, String serviceName) {
+            if (false) {
+                RuntimeException here = new RuntimeException("here");
+                here.fillInStackTrace();
+                Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
+                        + " to " + (mNumStartedServices-1), here);
+            }
             if (mCommonProcess != this) {
-                mCommonProcess.decStartedServices(memFactor, now);
+                mCommonProcess.decStartedServices(memFactor, now, serviceName);
             }
             mNumStartedServices--;
-            if (mNumStartedServices == 0 && mCurState == STATE_SERVICE_RESTARTING) {
-                setState(STATE_NOTHING, memFactor, now, null);
+            if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) {
+                setState(STATE_NOTHING, now);
             } else if (mNumStartedServices < 0) {
                 Slog.wtfStack(TAG, "Proc started services underrun: pkg="
                         + mPackage + " uid=" + mUid + " name=" + mName);
@@ -2873,6 +2923,8 @@
         public int mRunState = STATE_NOTHING;
         long mRunStartTime;
 
+        boolean mStarted;
+        boolean mRestarting;
         int mStartedCount;
         public int mStartedState = STATE_NOTHING;
         long mStartedStartTime;
@@ -2902,10 +2954,9 @@
                     // There was already an old owner, reset this object for its
                     // new owner.
                     mOwner = newOwner;
-                    if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
-                            || mExecState != STATE_NOTHING) {
+                    if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
                         long now = SystemClock.uptimeMillis();
-                        if (mStartedState != STATE_NOTHING) {
+                        if (mStarted) {
                             if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
                                     + " from " + mOwner + " while started: pkg="
                                     + mPackage + " service=" + mName + " proc=" + mProc);
@@ -2931,10 +2982,9 @@
         public void clearCurrentOwner(Object owner, boolean silently) {
             if (mOwner == owner) {
                 mProc.decActiveServices(mName);
-                if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
-                        || mExecState != STATE_NOTHING) {
+                if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) {
                     long now = SystemClock.uptimeMillis();
-                    if (mStartedState != STATE_NOTHING) {
+                    if (mStarted) {
                         if (!silently) {
                             Slog.wtfStack(TAG, "Service owner " + owner
                                     + " cleared while started: pkg=" + mPackage + " service="
@@ -3042,7 +3092,18 @@
             if (mOwner == null) {
                 Slog.wtf(TAG, "Starting service " + this + " without owner");
             }
+            mStarted = started;
+            updateStartedState(memFactor, now);
+        }
+
+        public void setRestarting(boolean restarting, int memFactor, long now) {
+            mRestarting = restarting;
+            updateStartedState(memFactor, now);
+        }
+
+        void updateStartedState(int memFactor, long now) {
             final boolean wasStarted = mStartedState != STATE_NOTHING;
+            final boolean started = mStarted || mRestarting;
             final int state = started ? memFactor : STATE_NOTHING;
             if (mStartedState != state) {
                 if (mStartedState != STATE_NOTHING) {
@@ -3056,9 +3117,9 @@
                 mProc = mProc.pullFixedProc(mPackage);
                 if (wasStarted != started) {
                     if (started) {
-                        mProc.incStartedServices(memFactor, now);
+                        mProc.incStartedServices(memFactor, now, mName);
                     } else {
-                        mProc.decStartedServices(memFactor, now);
+                        mProc.decStartedServices(memFactor, now, mName);
                     }
                 }
                 updateRunning(memFactor, now);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index a99aa33..0a702ff 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -84,7 +84,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 66 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 67 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -154,6 +154,8 @@
     final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
     final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
     final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>();
+    final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers =
+            new SparseArray<ArrayList<StopwatchTimer>>();
 
     // Last partial timers we use for distributing CPU usage.
     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
@@ -2404,6 +2406,14 @@
         getUidStatsLocked(uid).noteWifiScanStoppedLocked();
     }
 
+    public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
+        getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph);
+    }
+
+    public void noteWifiBatchedScanStoppedLocked(int uid) {
+        getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked();
+    }
+
     int mWifiMulticastNesting = 0;
 
     public void noteWifiMulticastEnabledLocked(int uid) {
@@ -2456,6 +2466,20 @@
         }
     }
 
+    public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) {
+        int N = ws.size();
+        for (int i=0; i<N; i++) {
+            noteWifiBatchedScanStartedLocked(ws.get(i), csph);
+        }
+    }
+
+    public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) {
+        int N = ws.size();
+        for (int i=0; i<N; i++) {
+            noteWifiBatchedScanStoppedLocked(ws.get(i));
+        }
+    }
+
     public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
@@ -2579,6 +2603,10 @@
         boolean mWifiScanStarted;
         StopwatchTimer mWifiScanTimer;
 
+        private static final int NO_BATCHED_SCAN_STARTED = -1;
+        int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
+        StopwatchTimer[] mWifiBatchedScanTimer;
+
         boolean mWifiMulticastEnabled;
         StopwatchTimer mWifiMulticastTimer;
 
@@ -2629,6 +2657,7 @@
                     mFullWifiLockTimers, mUnpluggables);
             mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
                     mWifiScanTimers, mUnpluggables);
+            mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
             mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
                     mWifiMulticastTimers, mUnpluggables);
         }
@@ -2719,6 +2748,36 @@
         }
 
         @Override
+        public void noteWifiBatchedScanStartedLocked(int csph) {
+            int bin = 0;
+            while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) {
+                csph = csph >> 3;
+                bin++;
+            }
+
+            if (mWifiBatchedScanBinStarted == bin) return;
+
+            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
+                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
+                        stopRunningLocked(BatteryStatsImpl.this);
+            }
+            mWifiBatchedScanBinStarted = bin;
+            if (mWifiBatchedScanTimer[bin] == null) {
+                makeWifiBatchedScanBin(bin, null);
+            }
+            mWifiBatchedScanTimer[bin].startRunningLocked(BatteryStatsImpl.this);
+        }
+
+        @Override
+        public void noteWifiBatchedScanStoppedLocked() {
+            if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
+                mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
+                        stopRunningLocked(BatteryStatsImpl.this);
+                mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
+            }
+        }
+
+        @Override
         public void noteWifiMulticastEnabledLocked() {
             if (!mWifiMulticastEnabled) {
                 mWifiMulticastEnabled = true;
@@ -2854,6 +2913,15 @@
         }
 
         @Override
+        public long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which) {
+            if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
+            if (mWifiBatchedScanTimer[csphBin] == null) {
+                return 0;
+            }
+            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(batteryRealtime, which);
+        }
+
+        @Override
         public long getWifiMulticastTime(long batteryRealtime, int which) {
             if (mWifiMulticastTimer == null) {
                 return 0;
@@ -2914,6 +2982,24 @@
             return mUserActivityCounters[type].getCountLocked(which);
         }
 
+        void makeWifiBatchedScanBin(int i, Parcel in) {
+            if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
+
+            ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i);
+            if (collected == null) {
+                collected = new ArrayList<StopwatchTimer>();
+                mWifiBatchedScanTimers.put(i, collected);
+            }
+            if (in == null) {
+                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
+                        mUnpluggables);
+            } else {
+                mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
+                        mUnpluggables, in);
+            }
+        }
+
+
         void initUserActivityLocked() {
             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
@@ -2974,6 +3060,14 @@
                 active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false);
                 active |= mWifiScanStarted;
             }
+            if (mWifiBatchedScanTimer != null) {
+                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
+                    if (mWifiBatchedScanTimer[i] != null) {
+                        active |= !mWifiBatchedScanTimer[i].reset(BatteryStatsImpl.this, false);
+                    }
+                }
+                active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
+            }
             if (mWifiMulticastTimer != null) {
                 active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false);
                 active |= mWifiMulticastEnabled;
@@ -3080,6 +3174,11 @@
                 if (mWifiScanTimer != null) {
                     mWifiScanTimer.detach();
                 }
+                for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
+                    if (mWifiBatchedScanTimer[i] != null) {
+                        mWifiBatchedScanTimer[i].detach();
+                    }
+                }
                 if (mWifiMulticastTimer != null) {
                     mWifiMulticastTimer.detach();
                 }
@@ -3157,6 +3256,14 @@
             } else {
                 out.writeInt(0);
             }
+            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
+                if (mWifiBatchedScanTimer[i] != null) {
+                    out.writeInt(1);
+                    mWifiBatchedScanTimer[i].writeToParcel(out, batteryRealtime);
+                } else {
+                    out.writeInt(0);
+                }
+            }
             if (mWifiMulticastTimer != null) {
                 out.writeInt(1);
                 mWifiMulticastTimer.writeToParcel(out, batteryRealtime);
@@ -3266,6 +3373,14 @@
             } else {
                 mWifiScanTimer = null;
             }
+            mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
+            for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
+                if (in.readInt() != 0) {
+                    makeWifiBatchedScanBin(i, in);
+                } else {
+                    mWifiBatchedScanTimer[i] = null;
+                }
+            }
             mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
                 mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
@@ -5463,6 +5578,13 @@
             if (in.readInt() != 0) {
                 u.mWifiScanTimer.readSummaryFromParcelLocked(in);
             }
+            u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED;
+            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
+                if (in.readInt() != 0) {
+                    u.makeWifiBatchedScanBin(i, null);
+                    u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in);
+                }
+            }
             u.mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
                 u.mWifiMulticastTimer.readSummaryFromParcelLocked(in);
@@ -5674,6 +5796,14 @@
             } else {
                 out.writeInt(0);
             }
+            for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
+                if (u.mWifiBatchedScanTimer[i] != null) {
+                    out.writeInt(1);
+                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+                } else {
+                    out.writeInt(0);
+                }
+            }
             if (u.mWifiMulticastTimer != null) {
                 out.writeInt(1);
                 u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL);
@@ -5909,6 +6039,7 @@
         mWifiRunningTimers.clear();
         mFullWifiLockTimers.clear();
         mWifiScanTimers.clear();
+        mWifiBatchedScanTimers.clear();
         mWifiMulticastTimers.clear();
 
         sNumSpeedSteps = in.readInt();
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 99a6843..94750d3 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -136,6 +136,13 @@
     public static final String POWER_CPU_SPEEDS = "cpu.speeds";
 
     /**
+     * Power consumed by wif batched scaning.  Broken down into bins by
+     * Channels Scanned per Hour.  May do 1-720 scans per hour of 1-100 channels
+     * for a range of 1-72,000.  Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)!
+     */
+    public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan";
+
+    /**
      * Battery capacity in milliAmpHour (mAh).
      */
     public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
@@ -171,7 +178,7 @@
 
                 String element = parser.getName();
                 if (element == null) break;
-                
+
                 if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
                     // Finish array
                     sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
index f97225e..c0cd93d 100644
--- a/core/res/res/layout/immersive_mode_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -37,8 +37,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:background="@drawable/cling_bg"
-            android:paddingLeft="14dp"
-            android:paddingRight="14dp"
+            android:paddingStart="14dp"
+            android:paddingEnd="14dp"
             android:paddingTop="24dp"
             android:paddingBottom="24dp">
             <TextView
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 997837a..4a16765 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1119,7 +1119,7 @@
     <string name="loading" msgid="7933681260296021180">"Indlæser…"</string>
     <string name="capital_on" msgid="1544682755514494298">"TIL"</string>
     <string name="capital_off" msgid="6815870386972805832">"FRA"</string>
-    <string name="whichApplication" msgid="4533185947064773386">"Fuldfør handling ved hjælp af"</string>
+    <string name="whichApplication" msgid="4533185947064773386">"Brug"</string>
     <string name="whichHomeApplication" msgid="4616420172727326782">"Vælg en startsideapp"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Brug som standard til denne handling."</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Ryd standard i Systemindstillinger &gt; Apps &gt; Downloadet."</string>
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 7af3b9c..3215e17 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -58,4 +58,12 @@
   </array>
   <!-- This is the battery capacity in mAh (measured at nominal voltage) -->
   <item name="battery.capacity">1000</item>
+
+  <array name="wifi.batchedscan"> <!-- mA -->
+      <value>.0002</value> <!-- 1-8/hr -->
+      <value>.002</value>  <!-- 9-64/hr -->
+      <value>.02</value>   <!-- 65-512/hr -->
+      <value>.2</value>    <!-- 513-4,096/hr -->
+      <value>2</value>    <!-- 4097-/hr -->
+  </array>
 </device>
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index af8441a..aac7876 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -88,9 +88,10 @@
     @Override
     public boolean getPadding(Rect padding) {
         final Rect r = mDrawableContainerState.getConstantPadding();
-        boolean result = true;
+        boolean result;
         if (r != null) {
             padding.set(r);
+            result = (r.left | r.top | r.bottom | r.right) != 0;
         } else {
             if (mCurrDrawable != null) {
                 result = mCurrDrawable.getPadding(padding);
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index ab34c0f..9c57a2c 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -244,7 +244,7 @@
         } else {
             padding.set(mPadding);
         }
-        return true;
+        return (padding.left | padding.top | padding.right | padding.bottom) != 0;
     }
 
     /**
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
index 2719c5c..349078f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
@@ -60,12 +60,12 @@
  */
 public class KeyguardTransportControlView extends FrameLayout {
 
-    private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
     private static final int RESET_TO_METADATA_DELAY = 5000;
     protected static final boolean DEBUG = false;
     protected static final String TAG = "TransportControlView";
 
     private static final boolean ANIMATE_TRANSITIONS = true;
+    protected static final long QUIESCENT_PLAYBACK_FACTOR = 1000;
 
     private ViewGroup mMetadataContainer;
     private ViewGroup mInfoContainer;
@@ -89,11 +89,9 @@
     private ImageView mBadge;
 
     private boolean mSeekEnabled;
-    private boolean mUserSeeking;
     private java.text.DateFormat mFormat;
 
-    private Date mTimeElapsed;
-    private Date mTrackDuration;
+    private Date mTempDate = new Date();
 
     /**
      * The metadata which should be populated into the view once we've been attached
@@ -111,18 +109,25 @@
 
         @Override
         public void onClientPlaybackStateUpdate(int state) {
-            setSeekBarsEnabled(false);
             updatePlayPauseState(state);
         }
 
         @Override
         public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs,
                 long currentPosMs, float speed) {
-            setSeekBarsEnabled(mMetadata != null && mMetadata.duration > 0);
             updatePlayPauseState(state);
             if (DEBUG) Log.d(TAG, "onClientPlaybackStateUpdate(state=" + state +
                     ", stateChangeTimeMs=" + stateChangeTimeMs + ", currentPosMs=" + currentPosMs +
                     ", speed=" + speed + ")");
+
+            removeCallbacks(mUpdateSeekBars);
+            // Since the music client may be responding to historical events that cause the
+            // playback state to change dramatically, wait until things become quiescent before
+            // resuming automatic scrub position update.
+            if (mTransientSeek.getVisibility() == View.VISIBLE
+                    && playbackPositionShouldMove(mCurrentPlayState)) {
+                postDelayed(mUpdateSeekBars, QUIESCENT_PLAYBACK_FACTOR);
+            }
         }
 
         @Override
@@ -136,15 +141,21 @@
         }
     };
 
-    private final Runnable mUpdateSeekBars = new Runnable() {
+    private class UpdateSeekBarRunnable implements  Runnable {
         public void run() {
-            if (updateSeekBars()) {
+            boolean seekAble = updateOnce();
+            if (seekAble) {
                 removeCallbacks(this);
                 postDelayed(this, 1000);
             }
         }
+        public boolean updateOnce() {
+            return updateSeekBars();
+        }
     };
 
+    private final UpdateSeekBarRunnable mUpdateSeekBars = new UpdateSeekBarRunnable();
+
     private final Runnable mResetToMetadata = new Runnable() {
         public void run() {
             resetToMetadata();
@@ -163,6 +174,7 @@
             }
             if (keyCode != -1) {
                 sendMediaButtonClick(keyCode);
+                delayResetToMetadata(); // if the scrub bar is showing, keep showing it.
             }
         }
     };
@@ -177,25 +189,67 @@
         }
     };
 
+    // This class is here to throttle scrub position updates to the music client
+    class FutureSeekRunnable implements Runnable {
+        private int mProgress;
+        private boolean mPending;
+
+        public void run() {
+            scrubTo(mProgress);
+            mPending = false;
+        }
+
+        void setProgress(int progress) {
+            mProgress = progress;
+            if (!mPending) {
+                mPending = true;
+                postDelayed(this, 30);
+            }
+        }
+    };
+
+    // This is here because RemoteControlClient's method isn't visible :/
+    private final static boolean playbackPositionShouldMove(int playstate) {
+        switch(playstate) {
+            case RemoteControlClient.PLAYSTATE_STOPPED:
+            case RemoteControlClient.PLAYSTATE_PAUSED:
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+            case RemoteControlClient.PLAYSTATE_ERROR:
+            case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
+            case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
+                return false;
+            case RemoteControlClient.PLAYSTATE_PLAYING:
+            case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
+            case RemoteControlClient.PLAYSTATE_REWINDING:
+            default:
+                return true;
+        }
+    }
+
+    private final FutureSeekRunnable mFutureSeekRunnable = new FutureSeekRunnable();
+
     private final SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener =
             new SeekBar.OnSeekBarChangeListener() {
         @Override
         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
             if (fromUser) {
-                scrubTo(progress);
+                mFutureSeekRunnable.setProgress(progress);
                 delayResetToMetadata();
+                mTempDate.setTime(progress);
+                mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate));
+            } else {
+                updateSeekDisplay();
             }
-            updateSeekDisplay();
         }
 
         @Override
         public void onStartTrackingTouch(SeekBar seekBar) {
-            mUserSeeking = true;
+            delayResetToMetadata();
+            removeCallbacks(mUpdateSeekBars); // don't update during user interaction
         }
 
         @Override
         public void onStopTrackingTouch(SeekBar seekBar) {
-            mUserSeeking = false;
         }
     };
 
@@ -247,17 +301,11 @@
         if (enabled == mSeekEnabled) return;
 
         mSeekEnabled = enabled;
-        if (mTransientSeek.getVisibility() == VISIBLE) {
+        if (mTransientSeek.getVisibility() == VISIBLE && !enabled) {
             mTransientSeek.setVisibility(INVISIBLE);
             mMetadataContainer.setVisibility(VISIBLE);
-            mUserSeeking = false;
             cancelResetToMetadata();
         }
-        if (enabled) {
-            mUpdateSeekBars.run();
-        } else {
-            removeCallbacks(mUpdateSeekBars);
-        }
     }
 
     public void setTransportControlCallback(KeyguardHostView.TransportControlCallback
@@ -294,6 +342,8 @@
         }
         final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
         setEnableMarquee(screenOn);
+        // Allow long-press anywhere else in this view to show the seek bar
+        setOnLongClickListener(mTransportShowSeekBarListener);
     }
 
     @Override
@@ -326,7 +376,6 @@
         mAudioManager.unregisterRemoteController(mRemoteController);
         KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor);
         mMetadata.clear();
-        mUserSeeking = false;
         removeCallbacks(mUpdateSeekBars);
     }
 
@@ -484,18 +533,12 @@
 
     void updateSeekDisplay() {
         if (mMetadata != null && mRemoteController != null && mFormat != null) {
-            if (mTimeElapsed == null) {
-                mTimeElapsed = new Date();
-            }
-            if (mTrackDuration == null) {
-                mTrackDuration = new Date();
-            }
-            mTimeElapsed.setTime(mRemoteController.getEstimatedMediaPosition());
-            mTrackDuration.setTime(mMetadata.duration);
-            mTransientSeekTimeElapsed.setText(mFormat.format(mTimeElapsed));
-            mTransientSeekTimeTotal.setText(mFormat.format(mTrackDuration));
+            mTempDate.setTime(mRemoteController.getEstimatedMediaPosition());
+            mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate));
+            mTempDate.setTime(mMetadata.duration);
+            mTransientSeekTimeTotal.setText(mFormat.format(mTempDate));
 
-            if (DEBUG) Log.d(TAG, "updateSeekDisplay timeElapsed=" + mTimeElapsed +
+            if (DEBUG) Log.d(TAG, "updateSeekDisplay timeElapsed=" + mTempDate +
                     " duration=" + mMetadata.duration);
         }
     }
@@ -508,10 +551,16 @@
             mTransientSeek.setVisibility(INVISIBLE);
             mMetadataContainer.setVisibility(VISIBLE);
             cancelResetToMetadata();
+            removeCallbacks(mUpdateSeekBars); // don't update if scrubber isn't visible
         } else {
             mTransientSeek.setVisibility(VISIBLE);
             mMetadataContainer.setVisibility(INVISIBLE);
             delayResetToMetadata();
+            if (playbackPositionShouldMove(mCurrentPlayState)) {
+                mUpdateSeekBars.run();
+            } else {
+                mUpdateSeekBars.updateOnce();
+            }
         }
         mTransportControlCallback.userActivity();
         return true;
@@ -573,9 +622,6 @@
             case RemoteControlClient.PLAYSTATE_PLAYING:
                 imageResId = R.drawable.ic_media_pause;
                 imageDescId = R.string.keyguard_transport_pause_description;
-                if (mSeekEnabled) {
-                    mUpdateSeekBars.run();
-                }
                 break;
 
             case RemoteControlClient.PLAYSTATE_BUFFERING:
@@ -590,10 +636,9 @@
                 break;
         }
 
-        if (state != RemoteControlClient.PLAYSTATE_PLAYING) {
-            removeCallbacks(mUpdateSeekBars);
-            updateSeekBars();
-        }
+        boolean clientSupportsSeek = mMetadata != null && mMetadata.duration > 0;
+        setSeekBarsEnabled(clientSupportsSeek);
+
         mBtnPlay.setImageResource(imageResId);
         mBtnPlay.setContentDescription(getResources().getString(imageDescId));
         mCurrentPlayState = state;
@@ -601,11 +646,9 @@
 
     boolean updateSeekBars() {
         final int position = (int) mRemoteController.getEstimatedMediaPosition();
+        if (DEBUG) Log.v(TAG, "Estimated time:" + position);
         if (position >= 0) {
-            if (DEBUG) Log.v(TAG, "Seek to " + position);
-            if (!mUserSeeking) {
-                mTransientSeekBar.setProgress(position);
-            }
+            mTransientSeekBar.setProgress(position);
             return true;
         }
         Log.w(TAG, "Updating seek bars; received invalid estimated media position (" +
@@ -671,34 +714,4 @@
     public boolean providesClock() {
         return false;
     }
-
-    private boolean wasPlayingRecently(int state, long stateChangeTimeMs) {
-        switch (state) {
-            case RemoteControlClient.PLAYSTATE_PLAYING:
-            case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
-            case RemoteControlClient.PLAYSTATE_REWINDING:
-            case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
-            case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
-            case RemoteControlClient.PLAYSTATE_BUFFERING:
-                // actively playing or about to play
-                return true;
-            case RemoteControlClient.PLAYSTATE_NONE:
-                return false;
-            case RemoteControlClient.PLAYSTATE_STOPPED:
-            case RemoteControlClient.PLAYSTATE_PAUSED:
-            case RemoteControlClient.PLAYSTATE_ERROR:
-                // we have stopped playing, check how long ago
-                if (DEBUG) {
-                    if ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS) {
-                        Log.v(TAG, "wasPlayingRecently: time < TIMEOUT was playing recently");
-                    } else {
-                        Log.v(TAG, "wasPlayingRecently: time > TIMEOUT");
-                    }
-                }
-                return ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS);
-            default:
-                Log.e(TAG, "Unknown playback state " + state + " in wasPlayingRecently()");
-                return false;
-        }
-    }
 }
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index b8287ae..a10a5a0 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Soekkassie vertoon"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Soekkassie weggesteek"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Voeg drukker by"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Kies drukker"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Vergeet drukker"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> drukker gekry"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> drukkers gekry"</item>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index d73cdd9..ae3d1f3 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"የፍለጋ ሳጥን ይታያል"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"የፍለጋ ሳጥን ተደብቋል"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"አታሚ አክል"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> አታሚ ተገኝቷል"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> አታሚዎች ተገኝተዋል"</item>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 14b6467..9be03cd 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"تم إظهار مربع البحث"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"تم إخفاء مربع البحث"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"إضافة طابعة"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"حدد الطابعة"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"تجاهل الطابعة"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"تم العثور على <xliff:g id="COUNT">%1$s</xliff:g> طابعة"</item>
     <item quantity="other" msgid="6533817036607128241">"تم العثور على <xliff:g id="COUNT">%1$s</xliff:g> من الطابعات"</item>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 47f86c6..85b96f32 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Полето за търсене е показано"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Полето за търсене е скрито"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Добавяне на принтер"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Намерен е <xliff:g id="COUNT">%1$s</xliff:g> принтер"</item>
     <item quantity="other" msgid="6533817036607128241">"Намерени са <xliff:g id="COUNT">%1$s</xliff:g> принтера"</item>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index fc60b0a..a429dd5 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Es mostra el quadre de cerca"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"S\'ha amagat el quadre de cerca"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Afegeix una impressora"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Selecciona una impressora"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Oblida la impressora"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"S\'ha trobat <xliff:g id="COUNT">%1$s</xliff:g> impressora"</item>
     <item quantity="other" msgid="6533817036607128241">"S\'han trobat <xliff:g id="COUNT">%1$s</xliff:g> impressores"</item>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 3f806d6..e85ea9b 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Vyhledávací pole se zobrazuje"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Vyhledávací pole je skryto"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Přidat tiskárnu"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Počet nalezených tiskáren: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
     <item quantity="other" msgid="6533817036607128241">"Počet nalezených tiskáren: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 60c22bb..74190b4 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Søgefeltet vises"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Søgefeltet er skjult"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Tilføj printer"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Vælg printer"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Glem printer"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Der blev fundet <xliff:g id="COUNT">%1$s</xliff:g> printer"</item>
     <item quantity="other" msgid="6533817036607128241">"Der blev fundet <xliff:g id="COUNT">%1$s</xliff:g> printere"</item>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index 54c936f..21289e0 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Suchfeld angezeigt"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Suchfeld ausgeblendet"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Drucker hinzufügen"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> Drucker gefunden"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> Drucker gefunden"</item>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index 168f87b..795e730 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Εμφάνιση πλαισίου αναζήτησης"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Απόκρυψη πλαισίου αναζήτησης"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Προσθήκη εκτυπωτή"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Επιλογή εκτυπωτή"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Διαγραφή εκτυπωτή"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Βρέθηκε <xliff:g id="COUNT">%1$s</xliff:g> εκτυπωτής"</item>
     <item quantity="other" msgid="6533817036607128241">"Βρέθηκαν <xliff:g id="COUNT">%1$s</xliff:g> εκτυπωτές"</item>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 98c3688..27372f8 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Search box shown"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Search box hidden"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Add printer"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Select printer"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Forget printer"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer found"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers found"</item>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 98c3688..27372f8 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Search box shown"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Search box hidden"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Add printer"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Select printer"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Forget printer"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer found"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers found"</item>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index bfdf933..1fd174d 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Cuadro de búsqueda visible"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Cuadro de búsqueda oculto"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Agregar impresora"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Se encontró <xliff:g id="COUNT">%1$s</xliff:g> impresora."</item>
     <item quantity="other" msgid="6533817036607128241">"Se encontraron <xliff:g id="COUNT">%1$s</xliff:g> impresoras."</item>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index 28df5f0..0225cad 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Cuadro de búsqueda visible"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Cuadro de búsqueda oculto"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Añadir impresora"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Borrar impresora"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Se ha encontrado <xliff:g id="COUNT">%1$s</xliff:g> impresora"</item>
     <item quantity="other" msgid="6533817036607128241">"Se han encontrado <xliff:g id="COUNT">%1$s</xliff:g> impresoras"</item>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 1114f9f..f4391c8 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Otsingukast on kuvatud"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Otsingukast on peidetud"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Lisa printer"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Leiti <xliff:g id="COUNT">%1$s</xliff:g> printer"</item>
     <item quantity="other" msgid="6533817036607128241">"Leiti <xliff:g id="COUNT">%1$s</xliff:g> printerit"</item>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 950ef92..9db965f 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"کادر جستجو نمایان شد"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"کادر جستجو پنهان شد"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"افزودن چاپگر"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> چاپگر یافت شد"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> چاپگر یافت شد"</item>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index 239afcf..bb43b6c 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Hakukenttä näkyvissä"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Hakukenttä piilotettu"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Lisää tulostin"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Löytyi <xliff:g id="COUNT">%1$s</xliff:g> tulostin"</item>
     <item quantity="other" msgid="6533817036607128241">"Löytyi <xliff:g id="COUNT">%1$s</xliff:g> tulostinta"</item>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 3880745..f42d85f6 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Champ de recherche affiché"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Champ de recherche masqué"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Ajouter une imprimante"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimante trouvée"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantes trouvées"</item>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 961d344..39e7493 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Champ de recherche affiché."</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Champ de recherche masqué."</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Ajouter une imprimante"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimante trouvée."</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantes trouvées."</item>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 4d1ddd8..af5745f 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"खोज बॉक्स प्रदर्शित है"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"खोज बॉक्स छिपा हुआ है"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"प्रिंटर जोड़ें"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर मिला"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर मिले"</item>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 50b56ff..ccc4664 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Okvir za pretraživanje prikazan je"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Okvir za pretraživanje skriven je"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Dodaj pisač"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Pronađen je <xliff:g id="COUNT">%1$s</xliff:g> pisač"</item>
     <item quantity="other" msgid="6533817036607128241">"Pronađen je sljedeći broj pisača: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 79912fc..6a0741b 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Keresőmező megjelenítve"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Keresőmező elrejtve"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Nyomtató hozzáadása"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Nyomtató kiválasztása"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Nyomtató elfelejtése"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> nyomtató észlelve"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> nyomtató észlelve"</item>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 7d95f7b..1fe3e2c 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Որոնման վանդակը ցուցադրված է"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Որոնման վանդակը թաքցվել է"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Ավելացնել տպիչ"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> տպիչ է գտնվել"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> տպիչ է գտնվել"</item>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 1206676..26c9c33 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Kotak telusur ditampilkan"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Kotak telusur disembunyikan"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Tambahkan printer"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer ditemukan"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printer ditemukan"</item>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index 4223188..96c3b48 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Casella di ricerca visualizzata"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Casella di ricerca nascosta"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Aggiungi stampante"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Seleziona stampante"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Elimina stampante"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> stampante trovata"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> stampanti trovate"</item>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 2a9e0df..3e0e732 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"תיבת החיפוש מוצגת"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"תיבת החיפוש מוסתרת"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"הוסף מדפסת"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"בחר מדפסת"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"שכח את המדפסת"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"נמצאה מדפסת <xliff:g id="COUNT">%1$s</xliff:g>"</item>
     <item quantity="other" msgid="6533817036607128241">"נמצאו <xliff:g id="COUNT">%1$s</xliff:g> מדפסות"</item>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index e6ae97a..6df1f2b1 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"検索ボックスは表示されています"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"検索ボックスは表示されていません"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"プリンタを追加"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g>台のプリンタが見つかりました"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g>台のプリンタが見つかりました"</item>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 3fc1f3a..5ffa81e 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"საძიებო ველი ნაჩვენებია"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"საძიებო ველი დამალულია"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"პრინტერის დამატება"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"ნაპოვნია <xliff:g id="COUNT">%1$s</xliff:g> პრინტერი"</item>
     <item quantity="other" msgid="6533817036607128241">"ნაპოვნია <xliff:g id="COUNT">%1$s</xliff:g> პრინტერი"</item>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 8ed85273..c00dee5 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"បាន​បង្ហាញ​ប្រ​អប់​ស្វែងរក"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"បាន​លាក់​ប្រអប់​ស្វែងរក"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"បន្ថែម​ម៉ាស៊ីន​បោះពុម្ព"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"រក​ឃើញ​ម៉ាស៊ីន​បោះពុម្ព <xliff:g id="COUNT">%1$s</xliff:g>"</item>
     <item quantity="other" msgid="6533817036607128241">"រក​ឃើញ​ម៉ាស៊ីន​បោះពុម្ព <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 83155fd..64c7ca6 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"검색창 표시됨"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"검색창 숨겨짐"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"프린터 추가"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"프린터 <xliff:g id="COUNT">%1$s</xliff:g>대 검색됨"</item>
     <item quantity="other" msgid="6533817036607128241">"프린터 <xliff:g id="COUNT">%1$s</xliff:g>대 검색됨"</item>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 45bb9bc..f954606 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ກ່ອງຊອກຫາຖືກສະແດງ"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ກ່ອງຊອກຫາຖືກເຊື່ອງ"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"ເພີ່ມເຄື່ອງພິມ"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"ເລືອກເຄື່ອງພິມ"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"ລືມເຄື່ອງພິມ"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"ພົບ <xliff:g id="COUNT">%1$s</xliff:g> ເຄື່ອງພິມ"</item>
     <item quantity="other" msgid="6533817036607128241">"ພົບ <xliff:g id="COUNT">%1$s</xliff:g> ເຄື່ອງພິມ"</item>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index 1560dce..0c4e386 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Paieškos laukelis rodomas"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Paieškos laukelis paslėptas"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Pridėti spausdintuvą"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Pasirinkti spausdintuvą"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Pamiršti spausdintuvą"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Rasta spausdintuvų: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
     <item quantity="other" msgid="6533817036607128241">"Rasta spausdintuvų: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 3a6049c..3fffdfe 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Meklēšanas lodziņš ir redzams."</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Meklēšanas lodziņš ir paslēpts."</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Pievienot printeri"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Atlasīt printeri"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Neatcerēties printeri"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Atrasts <xliff:g id="COUNT">%1$s</xliff:g> printeris"</item>
     <item quantity="other" msgid="6533817036607128241">"Atrasti <xliff:g id="COUNT">%1$s</xliff:g> printeri"</item>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index 8062eb1..e429387 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Хайлтын нүдийг гаргах"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Хайлтын нүдийг далдлах"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Принтер нэмэх"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Принтер сонгох"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Принтерийг мартах"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> принтер олдсон"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> принтер олдсон"</item>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index d113749..24059b1 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Kotak carian ditunjukkan"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Kotak carian tersembunyi"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Tambah pencetak"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> pencetak ditemui"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> pencetak ditemui"</item>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index abed60d..1344e11 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Søkefeltet vises"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Søkefeltet er skjult"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Legg til skriver"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Velg skriveren"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Glem skriveren"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> skriver ble funnet"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> skrivere ble funnet"</item>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 3289d12..dc12508 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Zoekvak weergegeven"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Zoekvak verborgen"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Printer toevoegen"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Printer selecteren"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Printer vergeten"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer gevonden"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers gevonden"</item>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 10cb2e7..fda4c14 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Pole wyszukiwania jest widoczne"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Pole wyszukiwania jest ukryte"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Dodaj drukarkę"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Znaleziono <xliff:g id="COUNT">%1$s</xliff:g> drukarkę"</item>
     <item quantity="other" msgid="6533817036607128241">"Znalezione drukarki: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 630fe03..6bfc395 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Caixa de pesquisa apresentada"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Caixa de pesquisa ocultada"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Adicionar impressora"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> impressora encontrada"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> impressoras encontradas"</item>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 6e5eab1..ae2603e 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Caixa de pesquisa exibida"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Caixa de pesquisa oculta"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Adicionar impressora"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> impressora encontrada"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> impressoras encontradas"</item>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index c4d9f8e..94d389a 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Caseta de căutare este afișată"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Caseta de căutare este ascunsă"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Adăugați o imprimantă"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantă găsită"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> (de) imprimante găsite"</item>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index b1335a0..5eb2d57 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Окно поиска показано"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Окно поиска скрыто"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Добавить принтер"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Найден <xliff:g id="COUNT">%1$s</xliff:g> принтер"</item>
     <item quantity="other" msgid="6533817036607128241">"Найдено принтеров: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 922a759..e868078 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Vyhľadávacie pole sa zobrazuje"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Vyhľadávacie pole je skryté"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Pridať tlačiareň"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Našla sa <xliff:g id="COUNT">%1$s</xliff:g> tlačiareň"</item>
     <item quantity="other" msgid="6533817036607128241">"Počet nájdených tlačiarní: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index abd07c6..018f56d 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Iskalno polje je prikazano"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Iskalno polje je skrito"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Dodajanje tiskalnika"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Najden <xliff:g id="COUNT">%1$s</xliff:g> tiskalnik"</item>
     <item quantity="other" msgid="6533817036607128241">"Število najdenih tiskalnikov: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 24f4797..cbab1a6 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Оквир за претрагу је приказан"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Оквир за претрагу је сакривен"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Додај штампач"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Изабери штампач"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Заборави штампач"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Пронађен је <xliff:g id="COUNT">%1$s</xliff:g> штампач"</item>
     <item quantity="other" msgid="6533817036607128241">"Пронађено је <xliff:g id="COUNT">%1$s</xliff:g> штампача"</item>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index 2d80858..9eb9930 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Sökrutan visas"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Sökrutan är dold"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Lägg till skrivare"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> skrivare hittades"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> skrivare hittades"</item>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 3873d37..c99ce0d 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Kisanduku cha kutafutia kimeonyeshwa"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Kisanduku cha kutafutia kimefichwa"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Ongeza printa"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Printa <xliff:g id="COUNT">%1$s</xliff:g> imepatikana"</item>
     <item quantity="other" msgid="6533817036607128241">"Printa <xliff:g id="COUNT">%1$s</xliff:g> zimepatikana"</item>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index 7d6523e..2f3ae1f 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"แสดงช่องค้นหาอยู่"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ซ่อนช่องค้นหาอยู่"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"เพิ่มเครื่องพิมพ์"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"พบเครื่องพิมพ์ <xliff:g id="COUNT">%1$s</xliff:g> เครื่อง"</item>
     <item quantity="other" msgid="6533817036607128241">"พบเครื่องพิมพ์ <xliff:g id="COUNT">%1$s</xliff:g> เครื่อง"</item>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 238c6bc..7fc1071 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Ipinapakita ang box para sa paghahanap"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Nakatago ang box para sa paghahanap"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Magdagdag ng printer"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer ang nakita"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> (na) printer ang nakita"</item>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index f851f20..1be7a04 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Arama kutusu gösteriliyor"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Arama kutusu gizli"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Yazıcı ekle"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> yazıcı bulundu"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> yazıcı bulundu"</item>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 8a340f1..4f526d0 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -41,6 +41,8 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Вікно пошуку показано"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Вікно пошуку сховано"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Додати принтер"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"Вибрати принтер"</string>
+    <string name="print_forget_printer" msgid="5035287497291910766">"Ігнорувати принтер"</string>
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Знайдено принтерів: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
     <item quantity="other" msgid="6533817036607128241">"Знайдено принтерів: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 7d086ad..6669e99 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Hiển thị hộp tìm kiếm"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Ẩn hộp tìm kiếm"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Thêm máy in"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"Đã tìm thấy <xliff:g id="COUNT">%1$s</xliff:g> máy in"</item>
     <item quantity="other" msgid="6533817036607128241">"Đã tìm thấy <xliff:g id="COUNT">%1$s</xliff:g> máy in"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 7e501f1..41f7d65 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"搜索框已显示"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"搜索框已隐藏"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"添加打印机"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"找到<xliff:g id="COUNT">%1$s</xliff:g>台打印机"</item>
     <item quantity="other" msgid="6533817036607128241">"找到<xliff:g id="COUNT">%1$s</xliff:g>台打印机"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 3856c75..9a0a2c9 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"搜尋框已顯示"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"搜尋框已隱藏"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"新增打印機"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 部打印機"</item>
     <item quantity="other" msgid="6533817036607128241">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 部打印機"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 81e0627..e76774c 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"搜尋框已顯示"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"搜尋框已隱藏"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"新增印表機"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 台印表機"</item>
     <item quantity="other" msgid="6533817036607128241">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 台印表機"</item>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index 03c499f..3310db8 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -41,6 +41,10 @@
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Ibhokisi lokuhlola libonisiwe"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Ibhokisi lokusesha lifihliwe"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"Engeza iphrinta"</string>
+    <!-- no translation found for print_select_printer (7388760939873368698) -->
+    <skip />
+    <!-- no translation found for print_forget_printer (5035287497291910766) -->
+    <skip />
   <plurals name="print_search_result_count_utterance">
     <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> iphrinta itholiwe"</item>
     <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> amaphrinta atholiwe"</item>
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 37504fb..2eef2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -314,11 +314,19 @@
                 collapsePanels();
                 final UserManager um = UserManager.get(mContext);
                 if (um.getUsers(true).size() > 1) {
-                    try {
-                        WindowManagerGlobal.getWindowManagerService().lockNow(null);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Couldn't show user switcher", e);
-                    }
+                    // Since keyguard and systemui were merged into the same process to save
+                    // memory, they share the same Looper and graphics context.  As a result,
+                    // there's no way to allow concurrent animation while keyguard inflates.
+                    // The workaround is to add a slight delay to allow the animation to finish.
+                    mHandler.postDelayed(new Runnable() {
+                        public void run() {
+                            try {
+                                WindowManagerGlobal.getWindowManagerService().lockNow(null);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "Couldn't show user switcher", e);
+                            }
+                        }
+                    }, 400); // TODO: ideally this would be tied to the collapse of the panel
                 } else {
                     Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
                             mContext, v, ContactsContract.Profile.CONTENT_URI,
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index ea0b978a..5476fde 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1187,6 +1187,7 @@
         if (!mRestartingServices.contains(r)) {
             r.createdFromFg = false;
             mRestartingServices.add(r);
+            r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
         }
 
         r.cancelNotification();
@@ -1220,6 +1221,9 @@
         if (removed || callingUid != r.appInfo.uid) {
             r.resetRestartCounter();
         }
+        if (removed) {
+            r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
+        }
         mAm.mHandler.removeCallbacks(r.restarter);
         return true;
     }
@@ -1243,7 +1247,9 @@
 
         // We are now bringing the service up, so no longer in the
         // restarting state.
-        mRestartingServices.remove(r);
+        if (mRestartingServices.remove(r)) {
+            r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis());
+        }
 
         // Make sure this service is no longer considered delayed, we are starting it now.
         if (r.delayed) {
@@ -1581,6 +1587,7 @@
             }
             r.app.services.remove(r);
             if (r.app.thread != null) {
+                updateServiceForegroundLocked(r.app, false);
                 try {
                     bumpServiceExecutingLocked(r, false, "destroy");
                     mDestroyingServices.add(r);
@@ -1591,7 +1598,6 @@
                             + r.shortName, e);
                     serviceProcessGoneLocked(r);
                 }
-                updateServiceForegroundLocked(r.app, false);
             } else {
                 if (DEBUG_SERVICE) Slog.v(
                     TAG, "Removed service that has no process: " + r);
@@ -1816,6 +1822,9 @@
                     r.tracker = null;
                 }
             }
+            if (finishing) {
+                r.app = null;
+            }
         }
     }
 
@@ -1960,8 +1969,7 @@
         }
     }
 
-    final void killServicesLocked(ProcessRecord app,
-            boolean allowRestart) {
+    final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
         // Report disconnected services.
         if (false) {
             // XXX we are letting the client link to the service for
@@ -1990,16 +1998,8 @@
             }
         }
 
-        // Clean up any connections this application has to other services.
-        for (int i=app.connections.size()-1; i>=0; i--) {
-            ConnectionRecord r = app.connections.valueAt(i);
-            removeConnectionLocked(r, app, null);
-        }
-        app.connections.clear();
-
+        // First clear app state from services.
         for (int i=app.services.size()-1; i>=0; i--) {
-            // Any services running in the application need to be placed
-            // back in the pending list.
             ServiceRecord sr = app.services.valueAt(i);
             synchronized (sr.stats.getBatteryStats()) {
                 sr.stats.stopLaunchedLocked();
@@ -2020,8 +2020,21 @@
                 b.binder = null;
                 b.requested = b.received = b.hasBound = false;
             }
+        }
 
-            if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
+        // Clean up any connections this application has to other services.
+        for (int i=app.connections.size()-1; i>=0; i--) {
+            ConnectionRecord r = app.connections.valueAt(i);
+            removeConnectionLocked(r, app, null);
+        }
+        app.connections.clear();
+
+        // Now do remaining service cleanup.
+        for (int i=app.services.size()-1; i>=0; i--) {
+            // Any services running in the application may need to be placed
+            // back in the pending list.
+            ServiceRecord sr = app.services.valueAt(i);
+            if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
                     &ApplicationInfo.FLAG_PERSISTENT) == 0) {
                 Slog.w(TAG, "Service crashed " + sr.crashCount
                         + " times, stopping: " + sr);
@@ -2054,6 +2067,17 @@
 
         if (!allowRestart) {
             app.services.clear();
+
+            // Make sure there are no more restarting services for this process.
+            for (int i=mRestartingServices.size()-1; i>=0; i--) {
+                ServiceRecord r = mRestartingServices.get(i);
+                if (r.processName.equals(app.processName) &&
+                        r.serviceInfo.applicationInfo.uid == app.info.uid) {
+                    mRestartingServices.remove(i);
+                    r.clearRestarting(mAm.mProcessStats.getMemFactorLocked(),
+                            SystemClock.uptimeMillis());
+                }
+            }
         }
 
         // Make sure we have no more records on the stopping list.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 164e7b7..fe83e9f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -11901,6 +11901,7 @@
         boolean dumpDalvik = false;
         boolean oomOnly = false;
         boolean isCompact = false;
+        boolean localOnly = false;
         
         int opti = 0;
         while (opti < args.length) {
@@ -11919,12 +11920,15 @@
                 isCompact = true;
             } else if ("--oom".equals(opt)) {
                 oomOnly = true;
+            } else if ("--local".equals(opt)) {
+                localOnly = true;
             } else if ("-h".equals(opt)) {
                 pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]");
                 pw.println("  -a: include all available information for each process.");
                 pw.println("  -d: include dalvik details when dumping process details.");
                 pw.println("  -c: dump in a compact machine-parseable representation.");
                 pw.println("  --oom: only show processes organized by oom adj.");
+                pw.println("  --local: only collect details locally, don't call process.");
                 pw.println("If [process] is specified it can be the name or ");
                 pw.println("pid of a specific process to dump.");
                 return;
@@ -12041,14 +12045,22 @@
                     mi.dalvikPrivateDirty = (int)tmpLong[0];
                 }
                 if (dumpDetails) {
-                    try {
-                        pw.flush();
-                        thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
-                                dumpDalvik, innerArgs);
-                    } catch (RemoteException e) {
-                        if (!isCheckinRequest) {
-                            pw.println("Got RemoteException!");
+                    if (localOnly) {
+                        ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails,
+                                dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0);
+                        if (isCheckinRequest) {
+                            pw.println();
+                        }
+                    } else {
+                        try {
                             pw.flush();
+                            thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
+                                    dumpDalvik, innerArgs);
+                        } catch (RemoteException e) {
+                            if (!isCheckinRequest) {
+                                pw.println("Got RemoteException!");
+                                pw.flush();
+                            }
                         }
                     }
                 }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 809452c..569440d 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -36,7 +36,6 @@
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
 
-import android.os.Trace;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.util.Objects;
 import com.android.server.Watchdog;
@@ -64,12 +63,14 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
@@ -1143,7 +1144,7 @@
                     } else if (isActivityOverHome(r)) {
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
                         showHomeBehindStack = true;
-                        behindFullscreen = true;
+                        behindFullscreen = !isHomeStack();
                     }
                 } else {
                     if (DEBUG_VISBILITY) Slog.v(
@@ -1910,26 +1911,38 @@
                 // bottom of the activity stack.  This also keeps it
                 // correctly ordered with any activities we previously
                 // moved.
+                final ThumbnailHolder newThumbHolder;
+                final TaskRecord targetTask;
                 final ActivityRecord bottom =
                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
-                        mTaskHistory.get(0).mActivities.get(0) : null;
+                                mTaskHistory.get(0).mActivities.get(0) : null;
                 if (bottom != null && target.taskAffinity != null
                         && target.taskAffinity.equals(bottom.task.affinity)) {
                     // If the activity currently at the bottom has the
                     // same task affinity as the one we are moving,
                     // then merge it into the same task.
-                    target.setTask(bottom.task, bottom.thumbHolder, false);
+                    targetTask = bottom.task;
+                    newThumbHolder = bottom.thumbHolder == null ? targetTask : bottom.thumbHolder;
                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
                             + " out to bottom task " + bottom.task);
                 } else {
-                    target.setTask(createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
-                            null, false), null, false);
-                    target.task.affinityIntent = target.intent;
+                    targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
+                            null, false);
+                    newThumbHolder = targetTask;
+                    targetTask.affinityIntent = target.intent;
                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
                             + " out to new task " + target.task);
                 }
 
-                final TaskRecord targetTask = target.task;
+                if (clearWhenTaskReset) {
+                    // This is the start of a new sub-task.
+                    if (target.thumbHolder == null) {
+                        target.thumbHolder = new ThumbnailHolder();
+                    }
+                } else {
+                    target.thumbHolder = newThumbHolder;
+                }
+
                 final int targetTaskId = targetTask.taskId;
                 mWindowManager.setAppGroupId(target.appToken, targetTaskId);
 
@@ -1950,8 +1963,8 @@
                         }
                     }
                     if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
-                            + task + " adding to task=" + targetTask,
-                            new RuntimeException("here").fillInStackTrace());
+                            + task + " adding to task=" + targetTask
+                            + " Callers=" + Debug.getCallers(4));
                     if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
                             + " out to target's task " + target.task);
                     p.setTask(targetTask, curThumbHolder, false);
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 0dd950e..2d59678 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -419,6 +419,20 @@
         }
     }
 
+    public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
+        }
+    }
+
+    public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
+        }
+    }
+
     public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
         enforceCallingPermission();
         synchronized (mStats) {
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 576adc2..423e540 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -27,7 +27,7 @@
  */
 final class ConnectionRecord {
     final AppBindRecord binding;    // The application/service binding.
-    final ActivityRecord activity;   // If non-null, the owning activity.
+    final ActivityRecord activity;  // If non-null, the owning activity.
     final IServiceConnection conn;  // The client connection.
     final int flags;                // Binding options.
     final int clientLabel;          // String resource labeling this client.
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 8d16880..e05fcda 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -750,23 +750,12 @@
                     return;
                 } else {
                     // Not an option, last argument must be a package name.
-                    try {
-                        IPackageManager pm = AppGlobals.getPackageManager();
-                        if (pm.getPackageUid(arg, UserHandle.getCallingUserId()) >= 0) {
-                            reqPackage = arg;
-                            // Include all details, since we know we are only going to
-                            // be dumping a smaller set of data.  In fact only the details
-                            // container per-package data, so that are needed to be able
-                            // to dump anything at all when filtering by package.
-                            dumpDetails = true;
-                        }
-                    } catch (RemoteException e) {
-                    }
-                    if (reqPackage == null) {
-                        pw.println("Unknown package: " + arg);
-                        dumpHelp(pw);
-                        return;
-                    }
+                    reqPackage = arg;
+                    // Include all details, since we know we are only going to
+                    // be dumping a smaller set of data.  In fact only the details
+                    // container per-package data, so that are needed to be able
+                    // to dump anything at all when filtering by package.
+                    dumpDetails = true;
                 }
             }
         }
@@ -816,13 +805,14 @@
             }
             return;
         } else if (aggregateHours != 0) {
+            pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
             dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
                     dumpDetails, dumpFullDetails, dumpAll, activeOnly);
             return;
         }
 
         boolean sepNeeded = false;
-        if (!currentOnly || isCheckin) {
+        if (dumpAll || isCheckin) {
             mWriteLock.lock();
             try {
                 ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
@@ -882,11 +872,11 @@
             }
         }
         if (!isCheckin) {
-            if (dumpAll) {
+            if (!currentOnly) {
                 if (sepNeeded) {
                     pw.println();
-                    pw.println("AGGREGATED OVER LAST 24 HOURS:");
                 }
+                pw.println("AGGREGATED OVER LAST 24 HOURS:");
                 dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
                         dumpDetails, dumpFullDetails, dumpAll, activeOnly);
                 pw.println();
@@ -901,8 +891,8 @@
                 } else {
                     if (sepNeeded) {
                         pw.println();
-                        pw.println("CURRENT STATS:");
                     }
+                    pw.println("CURRENT STATS:");
                     if (dumpDetails || dumpFullDetails) {
                         mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
                                 activeOnly);
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index cc1172a..84b1c3a 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -85,6 +85,7 @@
     ProcessRecord app;      // where this service is running or null.
     ProcessRecord isolatedProc; // keep track of isolated process, if requested
     ProcessStats.ServiceState tracker; // tracking service execution, may be null
+    ProcessStats.ServiceState restartTracker; // tracking service restart
     boolean delayed;        // are we waiting to start this service in the background?
     boolean isForeground;   // is service currently in foreground mode?
     int foregroundId;       // Notification ID of last foreground req.
@@ -340,6 +341,26 @@
         }
     }
 
+    public void makeRestarting(int memFactor, long now) {
+        if (restartTracker == null) {
+            if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
+                restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
+                        serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name);
+            }
+            if (restartTracker == null) {
+                return;
+            }
+        }
+        restartTracker.setRestarting(true, memFactor, now);
+    }
+
+    public void clearRestarting(int memFactor, long now) {
+        if (restartTracker != null) {
+            restartTracker.setRestarting(false, memFactor, now);
+            restartTracker = null;
+        }
+    }
+
     public AppBindRecord retrieveAppBindingLocked(Intent intent,
             ProcessRecord app) {
         Intent.FilterComparison filter = new Intent.FilterComparison(intent);
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index d471b57..f2efde1 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -369,15 +369,17 @@
     }
 
     private class BatchedScanRequest extends DeathRecipient {
-        BatchedScanSettings settings;
-        int uid;
-        int pid;
+        final BatchedScanSettings settings;
+        final int uid;
+        final int pid;
+        final WorkSource workSource;
 
-        BatchedScanRequest(BatchedScanSettings settings, IBinder binder) {
+        BatchedScanRequest(BatchedScanSettings settings, IBinder binder, WorkSource ws) {
             super(0, null, binder, null);
             this.settings = settings;
             this.uid = getCallingUid();
             this.pid = getCallingPid();
+            workSource = ws;
         }
         public void binderDied() {
             stopBatchedScan(settings, uid, pid);
@@ -406,12 +408,19 @@
     /**
      * see {@link android.net.wifi.WifiManager#requestBatchedScan()}
      */
-    public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder) {
+    public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder,
+            WorkSource workSource) {
         enforceChangePermission();
+        if (workSource != null) {
+            enforceWorkSourcePermission();
+            // WifiManager currently doesn't use names, so need to clear names out of the
+            // supplied WorkSource to allow future WorkSource combining.
+            workSource.clearNames();
+        }
         if (mBatchedScanSupported == false) return false;
         requested = new BatchedScanSettings(requested);
         if (requested.isInvalid()) return false;
-        BatchedScanRequest r = new BatchedScanRequest(requested, binder);
+        BatchedScanRequest r = new BatchedScanRequest(requested, binder, workSource);
         synchronized(mBatchedScanners) {
             mBatchedScanners.add(r);
             resolveBatchedScannersLocked();
@@ -468,18 +477,48 @@
 
     private void resolveBatchedScannersLocked() {
         BatchedScanSettings setting = new BatchedScanSettings();
+        WorkSource responsibleWorkSource = null;
         int responsibleUid = 0;
+        double responsibleCsph = 0; // Channel Scans Per Hour
 
         if (mBatchedScanners.size() == 0) {
-            mWifiStateMachine.setBatchedScanSettings(null, 0);
+            mWifiStateMachine.setBatchedScanSettings(null, 0, 0, null);
             return;
         }
         for (BatchedScanRequest r : mBatchedScanners) {
             BatchedScanSettings s = r.settings;
+
+            // evaluate responsibility
+            int currentChannelCount;
+            int currentScanInterval;
+            double currentCsph;
+
+            if (s.channelSet == null || s.channelSet.isEmpty()) {
+                // all channels - 11 B and 9 A channels roughly.
+                currentChannelCount = 9 + 11;
+            } else {
+                currentChannelCount = s.channelSet.size();
+                // these are rough est - no real need to correct for reg-domain;
+                if (s.channelSet.contains("A")) currentChannelCount += (9 - 1);
+                if (s.channelSet.contains("B")) currentChannelCount += (11 - 1);
+
+            }
+            if (s.scanIntervalSec == BatchedScanSettings.UNSPECIFIED) {
+                currentScanInterval = BatchedScanSettings.DEFAULT_INTERVAL_SEC;
+            } else {
+                currentScanInterval = s.scanIntervalSec;
+            }
+            currentCsph = 60 * 60 * currentChannelCount / currentScanInterval;
+
+            if (currentCsph > responsibleCsph) {
+                responsibleUid = r.uid;
+                responsibleWorkSource = r.workSource;
+                responsibleCsph = currentCsph;
+            }
+
             if (s.maxScansPerBatch != BatchedScanSettings.UNSPECIFIED &&
                     s.maxScansPerBatch < setting.maxScansPerBatch) {
                 setting.maxScansPerBatch = s.maxScansPerBatch;
-                responsibleUid = r.uid;
             }
             if (s.maxApPerScan != BatchedScanSettings.UNSPECIFIED &&
                     (setting.maxApPerScan == BatchedScanSettings.UNSPECIFIED ||
@@ -489,7 +528,6 @@
             if (s.scanIntervalSec != BatchedScanSettings.UNSPECIFIED &&
                     s.scanIntervalSec < setting.scanIntervalSec) {
                 setting.scanIntervalSec = s.scanIntervalSec;
-                responsibleUid = r.uid;
             }
             if (s.maxApForDistance != BatchedScanSettings.UNSPECIFIED &&
                     (setting.maxApForDistance == BatchedScanSettings.UNSPECIFIED ||
@@ -511,7 +549,8 @@
         }
 
         setting.constrain();
-        mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid);
+        mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid, (int)responsibleCsph,
+                responsibleWorkSource);
     }
 
     private void enforceAccessPermission() {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 5a1928c..149bda6 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -117,7 +117,7 @@
 
     void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable);
 
-    boolean requestBatchedScan(in BatchedScanSettings requested, IBinder binder);
+    boolean requestBatchedScan(in BatchedScanSettings requested, IBinder binder, in WorkSource ws);
 
     void stopBatchedScan(in BatchedScanSettings requested);
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7fc8bef..3b47e63 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -799,7 +799,13 @@
      */
     public boolean requestBatchedScan(BatchedScanSettings requested) {
         try {
-            return mService.requestBatchedScan(requested, new Binder());
+            return mService.requestBatchedScan(requested, new Binder(), null);
+        } catch (RemoteException e) { return false; }
+    }
+    /** @hide */
+    public boolean requestBatchedScan(BatchedScanSettings requested, WorkSource workSource) {
+        try {
+            return mService.requestBatchedScan(requested, new Binder(), workSource);
         } catch (RemoteException e) { return false; }
     }
 
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 520668e..c2f278a 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -39,7 +39,6 @@
 public class WifiNative {
 
     private static final boolean DBG = false;
-    private static final boolean VDBG = false;
     private final String mTAG;
     private static final int DEFAULT_GROUP_OWNER_INTENT     = 6;
 
@@ -118,12 +117,12 @@
 
     public boolean connectToSupplicant() {
         // No synchronization necessary .. it is implemented in WifiMonitor
-        if (VDBG) localLog(mInterfacePrefix + "connectToSupplicant");
+        localLog(mInterfacePrefix + "connectToSupplicant");
         return connectToSupplicantNative();
     }
 
     public void closeSupplicantConnection() {
-        if (VDBG) localLog(mInterfacePrefix + "closeSupplicantConnection");
+        localLog(mInterfacePrefix + "closeSupplicantConnection");
         closeSupplicantConnectionNative();
     }
 
@@ -136,9 +135,9 @@
         if (DBG) Log.d(mTAG, "doBoolean: " + command);
         synchronized (mLock) {
             int cmdId = getNewCmdIdLocked();
-            if (VDBG) localLog(cmdId + "->" + mInterfacePrefix + command);
+            localLog(cmdId + "->" + mInterfacePrefix + command);
             boolean result = doBooleanCommandNative(mInterfacePrefix + command);
-            if (VDBG) localLog(cmdId + "<-" + result);
+            localLog(cmdId + "<-" + result);
             if (DBG) Log.d(mTAG, "   returned " + result);
             return result;
         }
@@ -148,9 +147,9 @@
         if (DBG) Log.d(mTAG, "doInt: " + command);
         synchronized (mLock) {
             int cmdId = getNewCmdIdLocked();
-            if (VDBG) localLog(cmdId + "->" + mInterfacePrefix + command);
+            localLog(cmdId + "->" + mInterfacePrefix + command);
             int result = doIntCommandNative(mInterfacePrefix + command);
-            if (VDBG) localLog(cmdId + "<-" + result);
+            localLog(cmdId + "<-" + result);
             if (DBG) Log.d(mTAG, "   returned " + result);
             return result;
         }
@@ -160,9 +159,9 @@
         if (DBG) Log.d(mTAG, "doString: " + command);
         synchronized (mLock) {
             int cmdId = getNewCmdIdLocked();
-            if (VDBG) localLog(cmdId + "->" + mInterfacePrefix + command);
+            localLog(cmdId + "->" + mInterfacePrefix + command);
             String result = doStringCommandNative(mInterfacePrefix + command);
-            if (VDBG) localLog(cmdId + "<-" + result);
+            localLog(cmdId + "<-" + result);
             if (DBG) Log.d(mTAG, "   returned " + result);
             return result;
         }
@@ -298,7 +297,9 @@
      * the firmware can remember before it runs out of buffer space or -1 on error
      */
     public String setBatchedScanSettings(BatchedScanSettings settings) {
-        if (settings == null) return doStringCommand("DRIVER WLS_BATCHING STOP");
+        if (settings == null) {
+            return doStringCommand("DRIVER WLS_BATCHING STOP");
+        }
         String cmd = "DRIVER WLS_BATCHING SET SCANFREQ=" + settings.scanIntervalSec;
         cmd += " MSCAN=" + settings.maxScansPerBatch;
         if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 78da7e7..eedd66f 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -57,6 +57,7 @@
 import android.net.wifi.p2p.WifiP2pService;
 import android.os.BatteryStats;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.Message;
@@ -416,7 +417,8 @@
 
     /* change the batch scan settings.
      * arg1 = responsible UID
-     * obj = the new settings
+     * arg2 = csph (channel scans per hour)
+     * obj = bundle with the new settings and the optional worksource
      */
     public static final int CMD_SET_BATCHED_SCAN          = BASE + 135;
     public static final int CMD_START_NEXT_BATCHED_SCAN   = BASE + 136;
@@ -628,6 +630,15 @@
 
     private BatchedScanSettings mBatchedScanSettings = null;
 
+    /**
+     * Track the worksource/cost of the current settings and track what's been noted
+     * to the battery stats, so we can mark the end of the previous when changing.
+     */
+    private WorkSource mBatchedScanWorkSource = null;
+    private int mBatchedScanCsph = 0;
+    private WorkSource mNotedBatchedScanWorkSource = null;
+    private int mNotedBatchedScanCsph = 0;
+
 
     public WifiStateMachine(Context context, String wlanInterface) {
         super("WifiStateMachine");
@@ -841,8 +852,14 @@
     /**
      * start or stop batched scanning using the given settings
      */
-    public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid) {
-        sendMessage(CMD_SET_BATCHED_SCAN, callingUid, 0, settings);
+    private static final String BATCHED_SETTING = "batched_settings";
+    private static final String BATCHED_WORKSOURCE = "batched_worksource";
+    public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid, int csph,
+            WorkSource workSource) {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(BATCHED_SETTING, settings);
+        bundle.putParcelable(BATCHED_WORKSOURCE, workSource);
+        sendMessage(CMD_SET_BATCHED_SCAN, callingUid, csph, bundle);
     }
 
     public List<BatchedScanResult> syncGetBatchedScanResultsList() {
@@ -861,6 +878,8 @@
     }
 
     private void startBatchedScan() {
+        if (mBatchedScanSettings == null) return;
+
         if (mDhcpActive) {
             if (DBG) log("not starting Batched Scans due to DHCP");
             return;
@@ -872,10 +891,10 @@
         mAlarmManager.cancel(mBatchedScanIntervalIntent);
 
         String scansExpected = mWifiNative.setBatchedScanSettings(mBatchedScanSettings);
-
         try {
             mExpectedBatchedScans = Integer.parseInt(scansExpected);
             setNextBatchedAlarm(mExpectedBatchedScans);
+            if (mExpectedBatchedScans > 0) noteBatchedScanStart();
         } catch (NumberFormatException e) {
             stopBatchedScan();
             loge("Exception parsing WifiNative.setBatchedScanSettings response " + e);
@@ -918,25 +937,31 @@
     }
 
     // return true if new/different
-    private boolean recordBatchedScanSettings(BatchedScanSettings settings) {
-        if (DBG) log("set batched scan to " + settings);
+    private boolean recordBatchedScanSettings(int responsibleUid, int csph, Bundle bundle) {
+        BatchedScanSettings settings = bundle.getParcelable(BATCHED_SETTING);
+        WorkSource responsibleWorkSource = bundle.getParcelable(BATCHED_WORKSOURCE);
+
+        if (DBG) {
+            log("set batched scan to " + settings + " for uid=" + responsibleUid +
+                    ", worksource=" + responsibleWorkSource);
+        }
         if (settings != null) {
-            // TODO - noteBatchedScanStart(message.arg1);
             if (settings.equals(mBatchedScanSettings)) return false;
         } else {
             if (mBatchedScanSettings == null) return false;
-            // TODO - noteBatchedScanStop(message.arg1);
         }
         mBatchedScanSettings = settings;
+        if (responsibleWorkSource == null) responsibleWorkSource = new WorkSource(responsibleUid);
+        mBatchedScanWorkSource = responsibleWorkSource;
+        mBatchedScanCsph = csph;
         return true;
     }
 
     private void stopBatchedScan() {
         mAlarmManager.cancel(mBatchedScanIntervalIntent);
-        if (mBatchedScanSettings != null) {
-            retrieveBatchedScanData();
-            mWifiNative.setBatchedScanSettings(null);
-        }
+        retrieveBatchedScanData();
+        mWifiNative.setBatchedScanSettings(null);
+        noteBatchedScanStop();
     }
 
     private void setNextBatchedAlarm(int scansExpected) {
@@ -1164,6 +1189,44 @@
         }
     }
 
+    private void noteBatchedScanStart() {
+        // note the end of a previous scan set
+        if (mNotedBatchedScanWorkSource != null &&
+                (mNotedBatchedScanWorkSource.equals(mBatchedScanWorkSource) == false ||
+                 mNotedBatchedScanCsph != mBatchedScanCsph)) {
+            try {
+                mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource);
+            } catch (RemoteException e) {
+                log(e.toString());
+            } finally {
+                mNotedBatchedScanWorkSource = null;
+                mNotedBatchedScanCsph = 0;
+            }
+        }
+        // note the start of the new
+        try {
+            mBatteryStats.noteWifiBatchedScanStartedFromSource(mBatchedScanWorkSource,
+                    mBatchedScanCsph);
+            mNotedBatchedScanWorkSource = mBatchedScanWorkSource;
+            mNotedBatchedScanCsph = mBatchedScanCsph;
+        } catch (RemoteException e) {
+            log(e.toString());
+        }
+    }
+
+    private void noteBatchedScanStop() {
+        if (mNotedBatchedScanWorkSource != null) {
+            try {
+                mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource);
+            } catch (RemoteException e) {
+                log(e.toString());
+            } finally {
+                mNotedBatchedScanWorkSource = null;
+                mNotedBatchedScanCsph = 0;
+            }
+        }
+    }
+
     private void startScanNative(int type) {
         mWifiNative.scan(type);
         mScanResultIsPending = true;
@@ -1868,6 +1931,9 @@
            return;
         }
 
+        // note that all these splits and substrings keep references to the original
+        // huge string buffer while the amount we really want is generally pretty small
+        // so make copies instead (one example b/11087956 wasted 400k of heap here).
         synchronized(mScanResultCache) {
             mScanResults = new ArrayList<ScanResult>();
             String[] lines = scanResults.split("\n");
@@ -2307,9 +2373,7 @@
 
         mDhcpActive = false;
 
-        if (mBatchedScanSettings != null) {
-            startBatchedScan();
-        }
+        startBatchedScan();
     }
 
     private void handleSuccessfulIpConfiguration(DhcpResults dhcpResults) {
@@ -2447,7 +2511,7 @@
                     }
                     break;
                 case CMD_SET_BATCHED_SCAN:
-                    recordBatchedScanSettings((BatchedScanSettings)message.obj);
+                    recordBatchedScanSettings(message.arg1, message.arg2, (Bundle)message.obj);
                     break;
                 case CMD_POLL_BATCHED_SCAN:
                     handleBatchedScanPollRequest();
@@ -2960,9 +3024,7 @@
 
             mDhcpActive = false;
 
-            if (mBatchedScanSettings != null) {
-                startBatchedScan();
-            }
+            startBatchedScan();
 
             if (mOperationalMode != CONNECT_MODE) {
                 mWifiNative.disconnect();
@@ -3021,8 +3083,10 @@
                     startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
                     break;
                 case CMD_SET_BATCHED_SCAN:
-                    recordBatchedScanSettings((BatchedScanSettings)message.obj);
-                    startBatchedScan();
+                    if (recordBatchedScanSettings(message.arg1, message.arg2,
+                            (Bundle)message.obj)) {
+                        startBatchedScan();
+                    }
                     break;
                 case CMD_SET_COUNTRY_CODE:
                     String country = (String) message.obj;
@@ -3160,9 +3224,7 @@
             updateBatteryWorkSource(null);
             mScanResults = new ArrayList<ScanResult>();
 
-            if (mBatchedScanSettings != null) {
-                stopBatchedScan();
-            }
+            stopBatchedScan();
 
             final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);