Merge "Fix issue #11157301: Bad process stats when apps are binding to long-running services" into klp-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c5c7fe3..758273b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -182,6 +182,7 @@
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/effects/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index d8f9e49..188408d 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -191,13 +191,25 @@
     private long mChangingStagger = 0;
 
     /**
+     * Static interpolators - these are stateless and can be shared across the instances
+     */
+    private static TimeInterpolator ACCEL_DECEL_INTERPOLATOR =
+            new AccelerateDecelerateInterpolator();
+    private static TimeInterpolator DECEL_INTERPOLATOR = new DecelerateInterpolator();
+    private static TimeInterpolator sAppearingInterpolator = ACCEL_DECEL_INTERPOLATOR;
+    private static TimeInterpolator sDisappearingInterpolator = ACCEL_DECEL_INTERPOLATOR;
+    private static TimeInterpolator sChangingAppearingInterpolator = DECEL_INTERPOLATOR;
+    private static TimeInterpolator sChangingDisappearingInterpolator = DECEL_INTERPOLATOR;
+    private static TimeInterpolator sChangingInterpolator = DECEL_INTERPOLATOR;
+
+    /**
      * The default interpolators used for the animations
      */
-    private TimeInterpolator mAppearingInterpolator = new AccelerateDecelerateInterpolator();
-    private TimeInterpolator mDisappearingInterpolator = new AccelerateDecelerateInterpolator();
-    private TimeInterpolator mChangingAppearingInterpolator = new DecelerateInterpolator();
-    private TimeInterpolator mChangingDisappearingInterpolator = new DecelerateInterpolator();
-    private TimeInterpolator mChangingInterpolator = new DecelerateInterpolator();
+    private TimeInterpolator mAppearingInterpolator = sAppearingInterpolator;
+    private TimeInterpolator mDisappearingInterpolator = sDisappearingInterpolator;
+    private TimeInterpolator mChangingAppearingInterpolator = sChangingAppearingInterpolator;
+    private TimeInterpolator mChangingDisappearingInterpolator = sChangingDisappearingInterpolator;
+    private TimeInterpolator mChangingInterpolator = sChangingInterpolator;
 
     /**
      * These hashmaps are used to store the animations that are currently running as part of
@@ -905,14 +917,24 @@
                     case APPEARING:
                         startDelay = mChangingAppearingDelay + staggerDelay;
                         staggerDelay += mChangingAppearingStagger;
+                        if (mChangingAppearingInterpolator != sChangingAppearingInterpolator) {
+                            anim.setInterpolator(mChangingAppearingInterpolator);
+                        }
                         break;
                     case DISAPPEARING:
                         startDelay = mChangingDisappearingDelay + staggerDelay;
                         staggerDelay += mChangingDisappearingStagger;
+                        if (mChangingDisappearingInterpolator !=
+                                sChangingDisappearingInterpolator) {
+                            anim.setInterpolator(mChangingDisappearingInterpolator);
+                        }
                         break;
                     case CHANGING:
                         startDelay = mChangingDelay + staggerDelay;
                         staggerDelay += mChangingStagger;
+                        if (mChangingInterpolator != sChangingInterpolator) {
+                            anim.setInterpolator(mChangingInterpolator);
+                        }
                         break;
                 }
                 anim.setStartDelay(startDelay);
@@ -1148,6 +1170,9 @@
         anim.setTarget(child);
         anim.setStartDelay(mAppearingDelay);
         anim.setDuration(mAppearingDuration);
+        if (mAppearingInterpolator != sAppearingInterpolator) {
+            anim.setInterpolator(mAppearingInterpolator);
+        }
         if (anim instanceof ObjectAnimator) {
             ((ObjectAnimator) anim).setCurrentPlayTime(0);
         }
@@ -1192,6 +1217,9 @@
         Animator anim = mDisappearingAnim.clone();
         anim.setStartDelay(mDisappearingDelay);
         anim.setDuration(mDisappearingDuration);
+        if (mDisappearingInterpolator != sDisappearingInterpolator) {
+            anim.setInterpolator(mDisappearingInterpolator);
+        }
         anim.setTarget(child);
         final float preAnimAlpha = child.getAlpha();
         anim.addListener(new AnimatorListenerAdapter() {
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index e7e4a0f..6f929f2 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -513,7 +513,7 @@
         }
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothA2dp.Stub.asInterface(service);
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 5eb642c..5822e46 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -322,7 +322,8 @@
 
     /**
      * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} to
+     * receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PAIRING_REQUEST =
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 1962514..8ee955d 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -885,7 +885,7 @@
         return false;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothHeadset.Stub.asInterface(service);
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index b1a084a..2e950fa 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -519,7 +519,7 @@
         mServiceListener = null;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothHealth.Stub.asInterface(service);
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index f9c789c..844f432 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -458,7 +458,7 @@
         return BluetoothProfile.PRIORITY_OFF;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothInputDevice.Stub.asInterface(service);
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index fac8fd5..92a2f1e 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -142,7 +142,6 @@
                 try {
                     mService = null;
                     mContext.unbindService(mConnection);
-                    mConnection = null;
                 } catch (Exception re) {
                     Log.e(TAG,"",re);
                 }
@@ -370,7 +369,7 @@
         return PRIORITY_OFF;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) log("Proxy object connected");
             mService = IBluetoothMap.Stub.asInterface(service);
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 83d4329..b7a37f4 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -155,23 +155,34 @@
 
     /*package*/ void close() {
         if (VDBG) log("close()");
-        if (mConnection != null) {
-            mContext.unbindService(mConnection);
-            mConnection = null;
+
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mStateChangeCallback);
+            } catch (RemoteException re) {
+                Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mPanService != null) {
+                try {
+                    mPanService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
         }
         mServiceListener = null;
-        try {
-            mAdapter.getBluetoothManager().unregisterStateChangeCallback(mStateChangeCallback);
-        } catch (RemoteException re) {
-            Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re);
-        }
     }
 
     protected void finalize() {
         close();
     }
 
-    private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() {
+    final private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() {
 
         @Override
         public void onBluetoothStateChange(boolean on) throws RemoteException {
@@ -339,7 +350,7 @@
         return false;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
             mPanService = IBluetoothPan.Stub.asInterface(service);
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index c42251f..7f45652 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -197,7 +197,6 @@
                 try {
                     mService = null;
                     mContext.unbindService(mConnection);
-                    mConnection = null;
                 } catch (Exception re) {
                     Log.e(TAG,"",re);
                 }
@@ -300,7 +299,7 @@
         }
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) log("Proxy object connected");
             mService = IBluetoothPbap.Stub.asInterface(service);
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 648a4b3..78ac75f 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -178,7 +178,7 @@
         // If PAC URL is present in either then they must be equal.
         // Other parameters will only be for fall back.
         if (!TextUtils.isEmpty(mPacFileUrl)) {
-            return mPacFileUrl.equals(p.getPacFileUrl());
+            return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
         }
         if (!TextUtils.isEmpty(p.getPacFileUrl())) {
             return false;
@@ -219,6 +219,7 @@
         if (mPacFileUrl != null) {
             dest.writeByte((byte)1);
             dest.writeString(mPacFileUrl);
+            dest.writeInt(mPort);
             return;
         } else {
             dest.writeByte((byte)0);
@@ -244,7 +245,9 @@
                 String host = null;
                 int port = 0;
                 if (in.readByte() != 0) {
-                    return new ProxyProperties(in.readString());
+                    String url = in.readString();
+                    int localPort = in.readInt();
+                    return new ProxyProperties(url, localPort);
                 }
                 if (in.readByte() != 0) {
                     host = in.readString();
diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl
index 96b168d..5f06b83 100644
--- a/core/java/android/print/IPrintSpooler.aidl
+++ b/core/java/android/print/IPrintSpooler.aidl
@@ -48,4 +48,5 @@
             int sequence);
     void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId);
     void setClient(IPrintSpoolerClient client);
+    void setPrintJobCancelling(in PrintJobId printJobId, boolean cancelling);
 }
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index ccb4f44..92bda40 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -153,6 +153,9 @@
     /** Information about the printed document. */
     private PrintDocumentInfo mDocumentInfo;
 
+    /** Whether we are trying to cancel this print job. */
+    private boolean mCanceling;
+
     /** @hide*/
     public PrintJobInfo() {
         /* do nothing */
@@ -174,6 +177,7 @@
         mPageRanges = other.mPageRanges;
         mAttributes = other.mAttributes;
         mDocumentInfo = other.mDocumentInfo;
+        mCanceling = other.mCanceling;
     }
 
     private PrintJobInfo(Parcel parcel) {
@@ -201,6 +205,7 @@
         if (parcel.readInt() == 1) {
             mDocumentInfo = PrintDocumentInfo.CREATOR.createFromParcel(parcel);
         }
+        mCanceling = (parcel.readInt() == 1);
     }
 
     /**
@@ -503,6 +508,28 @@
         mDocumentInfo = info;
     }
 
+    /**
+     * Gets whether this print is being cancelled.
+     *
+     * @return True if the print job is being cancelled.
+     *
+     * @hide
+     */
+    public boolean isCancelling() {
+        return mCanceling;
+    }
+
+    /**
+     * Sets whether this print is being cancelled.
+     *
+     * @param cancelling True if the print job is being cancelled.
+     *
+     * @hide
+     */
+    public void setCancelling(boolean cancelling) {
+        mCanceling = cancelling;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -539,6 +566,7 @@
         } else {
             parcel.writeInt(0);
         }
+        parcel.writeInt(mCanceling ? 1 : 0);
     }
 
     @Override
@@ -556,6 +584,7 @@
                 ? mAttributes.toString() : null));
         builder.append(", documentInfo: " + (mDocumentInfo != null
                 ? mDocumentInfo.toString() : null));
+        builder.append(", cancelling: " + mCanceling);
         builder.append(", pages: " + (mPageRanges != null
                 ? Arrays.toString(mPageRanges) : null));
         builder.append("}");
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 9c7c1fe..1cb4e8d 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -48,6 +48,7 @@
  * <p>
  * To obtain a handle to the print manager do the following:
  * </p>
+ * 
  * <pre>
  * PrintManager printManager =
  *         (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
@@ -59,6 +60,9 @@
 
     private static final boolean DEBUG = false;
 
+    private static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 1;
+    private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 2;
+
     /** @hide */
     public static final int APP_ID_ANY = -2;
 
@@ -81,18 +85,17 @@
 
         /**
          * Callback notifying that a print job state changed.
-         *
+         * 
          * @param printJobId The print job id.
          */
-        public void onPrintJobsStateChanged(PrintJobId printJobId);
+        public void onPrintJobStateChanged(PrintJobId printJobId);
     }
 
     /**
      * Creates a new instance.
-     *
+     * 
      * @param context The current context in which to operate.
      * @param service The backing system service.
-     *
      * @hide
      */
     public PrintManager(Context context, IPrintManager service, int userId, int appId) {
@@ -104,14 +107,29 @@
         mHandler = new Handler(context.getMainLooper(), null, false) {
             @Override
             public void handleMessage(Message message) {
-                SomeArgs args = (SomeArgs) message.obj;
-                Context context = (Context) args.arg1;
-                IntentSender intent = (IntentSender) args.arg2;
-                args.recycle();
-                try {
-                    context.startIntentSender(intent, null, 0, 0, 0);
-                } catch (SendIntentException sie) {
-                    Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
+                switch (message.what) {
+                    case MSG_START_PRINT_JOB_CONFIG_ACTIVITY: {
+                        SomeArgs args = (SomeArgs) message.obj;
+                        Context context = (Context) args.arg1;
+                        IntentSender intent = (IntentSender) args.arg2;
+                        args.recycle();
+                        try {
+                            context.startIntentSender(intent, null, 0, 0, 0);
+                        } catch (SendIntentException sie) {
+                            Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
+                        }
+                    }
+                        break;
+
+                    case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: {
+                        SomeArgs args = (SomeArgs) message.obj;
+                        PrintJobStateChangeListener listener =
+                                (PrintJobStateChangeListener) args.arg1;
+                        PrintJobId printJobId = (PrintJobId) args.arg2;
+                        args.recycle();
+                        listener.onPrintJobStateChanged(printJobId);
+                    }
+                        break;
                 }
             }
         };
@@ -119,10 +137,10 @@
 
     /**
      * Creates an instance that can access all print jobs.
-     *
+     * 
      * @param userId The user id for which to get all print jobs.
-     * @return An instance if the caller has the permission to access
-     * all print jobs, null otherwise.
+     * @return An instance if the caller has the permission to access all print
+     *         jobs, null otherwise.
      * @hide
      */
     public PrintManager getGlobalPrintManagerForUser(int userId) {
@@ -140,9 +158,8 @@
 
     /**
      * Adds a listener for observing the state of print jobs.
-     *
+     * 
      * @param listener The listener to add.
-     *
      * @hide
      */
     public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
@@ -151,7 +168,7 @@
                     PrintJobStateChangeListenerWrapper>();
         }
         PrintJobStateChangeListenerWrapper wrappedListener =
-                new PrintJobStateChangeListenerWrapper(listener);
+                new PrintJobStateChangeListenerWrapper(listener, mHandler);
         try {
             mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId);
             mPrintJobStateChangeListeners.put(listener, wrappedListener);
@@ -162,9 +179,8 @@
 
     /**
      * Removes a listener for observing the state of print jobs.
-     *
+     * 
      * @param listener The listener to remove.
-     *
      * @hide
      */
     public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
@@ -188,11 +204,9 @@
 
     /**
      * Gets a print job given its id.
-     *
+     * 
      * @return The print job list.
-     *
      * @see PrintJob
-     *
      * @hide
      */
     public PrintJob getPrintJob(PrintJobId printJobId) {
@@ -209,9 +223,8 @@
 
     /**
      * Gets the print jobs for this application.
-     *
+     * 
      * @return The print job list.
-     *
      * @see PrintJob
      */
     public List<PrintJob> getPrintJobs() {
@@ -249,9 +262,9 @@
     }
 
     /**
-     * Creates a print job for printing a {@link PrintDocumentAdapter} with default print
-     * attributes.
-     *
+     * Creates a print job for printing a {@link PrintDocumentAdapter} with
+     * default print attributes.
+     * 
      * @param printJobName A name for the new print job.
      * @param documentAdapter An adapter that emits the document to print.
      * @param attributes The default print job attributes.
@@ -279,9 +292,8 @@
 
     /**
      * Gets the list of enabled print services.
-     *
+     * 
      * @return The enabled service list or an empty list.
-     *
      * @hide
      */
     public List<PrintServiceInfo> getEnabledPrintServices() {
@@ -298,9 +310,8 @@
 
     /**
      * Gets the list of installed print services.
-     *
+     * 
      * @return The installed service list or an empty list.
-     *
      * @hide
      */
     public List<PrintServiceInfo> getInstalledPrintServices() {
@@ -337,7 +348,8 @@
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = manager.mContext;
                 args.arg2 = intent;
-                manager.mHandler.obtainMessage(0, args).sendToTarget();
+                manager.mHandler.obtainMessage(MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
+                        args).sendToTarget();
             }
         }
     }
@@ -348,7 +360,8 @@
 
         private CancellationSignal mLayoutOrWriteCancellation;
 
-        private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in finish()
+        private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK -
+                                                       // cleared in finish()
 
         private Handler mHandler; // Strong reference OK - cleared in finish()
 
@@ -537,7 +550,8 @@
                 switch (message.what) {
                     case MSG_START: {
                         mDocumentAdapter.onStart();
-                    } break;
+                    }
+                        break;
 
                     case MSG_LAYOUT: {
                         final CancellationSignal cancellation;
@@ -559,14 +573,15 @@
                                     new MyLayoutResultCallback(layoutSpec.callback,
                                             layoutSpec.sequence), layoutSpec.metadata);
                         }
-                    } break;
+                    }
+                        break;
 
                     case MSG_WRITE: {
                         final CancellationSignal cancellation;
                         final WriteSpec writeSpec;
 
                         synchronized (mLock) {
-                            writeSpec= mLastWriteSpec;
+                            writeSpec = mLastWriteSpec;
                             mLastWriteSpec = null;
                             cancellation = new CancellationSignal();
                             mLayoutOrWriteCancellation = cancellation;
@@ -580,7 +595,8 @@
                                     cancellation, new MyWriteResultCallback(writeSpec.callback,
                                             writeSpec.fd, writeSpec.sequence));
                         }
-                    } break;
+                    }
+                        break;
 
                     case MSG_FINISH: {
                         if (DEBUG) {
@@ -588,7 +604,8 @@
                         }
                         mDocumentAdapter.onFinish();
                         doFinish();
-                    } break;
+                    }
+                        break;
 
                     default: {
                         throw new IllegalArgumentException("Unknown message: "
@@ -727,17 +744,26 @@
     private static final class PrintJobStateChangeListenerWrapper extends
             IPrintJobStateChangeListener.Stub {
         private final WeakReference<PrintJobStateChangeListener> mWeakListener;
+        private final WeakReference<Handler> mWeakHandler;
 
-        public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener) {
+        public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener,
+                Handler handler) {
             mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener);
+            mWeakHandler = new WeakReference<Handler>(handler);
         }
 
         @Override
         public void onPrintJobStateChanged(PrintJobId printJobId) {
+            Handler handler = mWeakHandler.get();
             PrintJobStateChangeListener listener = mWeakListener.get();
-            if (listener != null) {
-                listener.onPrintJobsStateChanged(printJobId);
+            if (handler != null && listener != null) {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = listener;
+                args.arg2 = printJobId;
+                handler.obtainMessage(MSG_NOTIFY_PRINT_JOB_STATE_CHANGED,
+                        args).sendToTarget();
             }
         }
     }
+
 }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
index 7dd1e8a..a9473a8 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
@@ -67,11 +67,12 @@
         if (ENABLED) {
             final int eventType = event.getEventType();
             switch (eventType) {
+                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
+                    // If the active window changes, clear the cache.
                     final int windowId = event.getWindowId();
-                    // If a new window, we clear the cache.
                     if (mWindowId != windowId) {
                         mWindowId = windowId;
                         clear();
diff --git a/core/java/com/android/internal/inputmethod/InputMethodRoot.java b/core/java/com/android/internal/inputmethod/InputMethodRoot.java
index f070a58..40a424b 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodRoot.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodRoot.java
@@ -17,15 +17,15 @@
 package com.android.internal.inputmethod;
 
 import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 public class InputMethodRoot extends LinearLayout {
-    private final Rect mGuardRect = new Rect();
-    private final Paint mGuardPaint = new Paint();
+
+    private View mNavigationGuard;
 
     public InputMethodRoot(Context context) {
         this(context, null);
@@ -37,25 +37,19 @@
 
     public InputMethodRoot(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs);
-        setWillNotDraw(false);
-        mGuardPaint.setColor(context.getResources()
-                .getColor(com.android.internal.R.color.input_method_navigation_guard));
     }
 
     @Override
     protected boolean fitSystemWindows(Rect insets) {
-        setPadding(0, 0, 0, insets.bottom);
+        if (mNavigationGuard == null) {
+            mNavigationGuard = findViewById(com.android.internal.R.id.navigationGuard);
+        }
+        if (mNavigationGuard == null) {
+            return super.fitSystemWindows(insets);
+        }
+        ViewGroup.LayoutParams lp = mNavigationGuard.getLayoutParams();
+        lp.height = insets.bottom;
+        mNavigationGuard.setLayoutParams(lp);
         return true;
     }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-
-        // draw navigation bar guard
-        final int w = getMeasuredWidth();
-        final int h = getMeasuredHeight();
-        mGuardRect.set(0, h - getPaddingBottom(), w, h);
-        canvas.drawRect(mGuardRect, mGuardPaint);
-    }
 }
diff --git a/core/res/res/drawable-hdpi/stat_sys_gps_on.png b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
index cb8a1e8..e0f7740 100644
--- a/core/res/res/drawable-hdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_gps_on.png b/core/res/res/drawable-ldpi/stat_sys_gps_on.png
index 8915c59..77776f5 100644
--- a/core/res/res/drawable-ldpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-ldpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_gps_on.png b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
index 2c98972..311a1de 100644
--- a/core/res/res/drawable-mdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xhdpi/stat_sys_gps_on.png
index a7408d4..8a6edfb 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
index 81fb04a..063f614 100755
--- a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/layout/input_method.xml b/core/res/res/layout/input_method.xml
index 23d7189..00a3990 100644
--- a/core/res/res/layout/input_method.xml
+++ b/core/res/res/layout/input_method.xml
@@ -52,4 +52,9 @@
         android:layout_height="wrap_content"
         android:visibility="gone">
     </FrameLayout>
+
+    <View android:id="@+id/navigationGuard"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="@+color/input_method_navigation_guard"/>
 </com.android.internal.inputmethod.InputMethodRoot>
diff --git a/core/res/res/values-mcc204/config.xml b/core/res/res/values-mcc204/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc204/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc206/config.xml b/core/res/res/values-mcc206/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc206/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc208/config.xml b/core/res/res/values-mcc208/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc208/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc214/config.xml b/core/res/res/values-mcc214/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc214/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc216/config.xml b/core/res/res/values-mcc216/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc216/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc219/config.xml b/core/res/res/values-mcc219/config.xml
index 80f4e58..7ae82fa 100644
--- a/core/res/res/values-mcc219/config.xml
+++ b/core/res/res/values-mcc219/config.xml
@@ -29,7 +29,4 @@
         <item>"96"</item>
     </string-array>
 
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
 </resources>
diff --git a/core/res/res/values-mcc222/config.xml b/core/res/res/values-mcc222/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc222/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc226/config.xml b/core/res/res/values-mcc226/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc226/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc228/config.xml b/core/res/res/values-mcc228/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc228/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc230/config.xml b/core/res/res/values-mcc230/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc230/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc231/config.xml b/core/res/res/values-mcc231/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc231/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc232/config.xml b/core/res/res/values-mcc232/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc232/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc234/config.xml b/core/res/res/values-mcc234/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc234/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc238/config.xml b/core/res/res/values-mcc238/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc238/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc240/config.xml b/core/res/res/values-mcc240/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc240/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc242/config.xml b/core/res/res/values-mcc242/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc242/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc244/config.xml b/core/res/res/values-mcc244/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc244/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc246/config.xml b/core/res/res/values-mcc246/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc246/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc247/config.xml b/core/res/res/values-mcc247/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc247/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc248/config.xml b/core/res/res/values-mcc248/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc248/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc260/config.xml b/core/res/res/values-mcc260/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc260/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc262/config.xml b/core/res/res/values-mcc262/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc262/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc268/config.xml b/core/res/res/values-mcc268/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc268/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc270/config.xml b/core/res/res/values-mcc270/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc270/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc272/config.xml b/core/res/res/values-mcc272/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc272/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc274/config.xml b/core/res/res/values-mcc274/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc274/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc278/config.xml b/core/res/res/values-mcc278/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc278/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc280/config.xml b/core/res/res/values-mcc280/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc280/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc284/config.xml b/core/res/res/values-mcc284/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc284/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc286/config.xml b/core/res/res/values-mcc286/config.xml
index f73a523..d99d051 100644
--- a/core/res/res/values-mcc286/config.xml
+++ b/core/res/res/values-mcc286/config.xml
@@ -61,7 +61,4 @@
          to enable use of the new Release 9 tables for Indic languages. -->
     <!-- <integer-array name="config_sms_enabled_locking_shift_tables"></integer-array> -->
 
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
 </resources>
diff --git a/core/res/res/values-mcc293/config.xml b/core/res/res/values-mcc293/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc293/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc294/config.xml b/core/res/res/values-mcc294/config.xml
deleted file mode 100644
index 8d6d3b1..0000000
--- a/core/res/res/values-mcc294/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
-
-</resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc310/config.xml
similarity index 92%
rename from core/res/res/values-mcc202/config.xml
rename to core/res/res/values-mcc310/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc310/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc311/config.xml
similarity index 92%
copy from core/res/res/values-mcc202/config.xml
copy to core/res/res/values-mcc311/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc311/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc312/config.xml
similarity index 92%
copy from core/res/res/values-mcc202/config.xml
copy to core/res/res/values-mcc312/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc312/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc313/config.xml
similarity index 92%
copy from core/res/res/values-mcc202/config.xml
copy to core/res/res/values-mcc313/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc313/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc314/config.xml
similarity index 92%
copy from core/res/res/values-mcc202/config.xml
copy to core/res/res/values-mcc314/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc314/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc315/config.xml
similarity index 92%
copy from core/res/res/values-mcc202/config.xml
copy to core/res/res/values-mcc315/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc315/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc316/config.xml
similarity index 92%
copy from core/res/res/values-mcc202/config.xml
copy to core/res/res/values-mcc316/config.xml
index 8d6d3b1..df398f9 100644
--- a/core/res/res/values-mcc202/config.xml
+++ b/core/res/res/values-mcc316/config.xml
@@ -20,6 +20,6 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">true</bool>
+    <bool name="config_safe_media_volume_enabled">false</bool>
 
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 429a8a4..56c4d9e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1148,7 +1148,7 @@
     <bool name="config_useDevInputEventForAudioJack">false</bool>
 
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
-    <bool name="config_safe_media_volume_enabled">false</bool>
+    <bool name="config_safe_media_volume_enabled">true</bool>
 
     <!-- Set to true if the wifi display supports compositing content stored
          in gralloc protected buffers.  For this to be true, there must exist
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index edfdcc2..adcb3fb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -105,6 +105,7 @@
   <java-symbol type="id" name="month" />
   <java-symbol type="id" name="month_name" />
   <java-symbol type="id" name="name" />
+  <java-symbol type="id" name="navigationGuard" />
   <java-symbol type="id" name="next" />
   <java-symbol type="id" name="next_button" />
   <java-symbol type="id" name="new_app_action" />
diff --git a/packages/Keyguard/res/values-mcc262-mnc07/bools.xml b/packages/Keyguard/res/values-mcc262-mnc07/bools.xml
new file mode 100644
index 0000000..6cd4c55
--- /dev/null
+++ b/packages/Keyguard/res/values-mcc262-mnc07/bools.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <!-- Carriers in this locale are sensitive to capitalization of carrier text. 
+         This makes the entire interface consistent by switching back to normal case. -->
+    <bool name="kg_use_all_caps">false</bool>
+</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
index 146c092..7d1f24f 100644
--- a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
+++ b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
@@ -19,11 +19,13 @@
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -55,15 +57,17 @@
     private final WindowManager mWindowManager;
     private final Point mRenderedSize = new Point();
     private final int[] mTmpLoc = new int[2];
-    private final Rect mTmpRect = new Rect();
 
     private long mLaunchCameraStart;
     private boolean mActive;
     private boolean mTransitioning;
     private boolean mDown;
 
+    private final Rect mInsets = new Rect();
+
     private FixedSizeFrameLayout mPreview;
     private View mFullscreenPreview;
+    private View mFakeNavBar;
 
     private final Runnable mTransitionToCameraRunnable = new Runnable() {
         @Override
@@ -211,10 +215,11 @@
 
     private void render() {
         final View root = getRootView();
-        final int width = root.getWidth();
-        final int height = root.getHeight();
+        final int width = root.getWidth() - mInsets.right;    // leave room
+        final int height = root.getHeight() - mInsets.bottom; // for bars
         if (mRenderedSize.x == width && mRenderedSize.y == height) {
-            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height));
+            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s %d%%",
+                    width, height, (int)(100*mPreview.getScaleX())));
             return;
         }
         if (width == 0 || height == 0) {
@@ -246,8 +251,8 @@
         mPreview.setTranslationY(pvTransY);
 
         mRenderedSize.set(width, height);
-        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s",
-                width, height, instanceId()));
+        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s %d%% instance=%s",
+                width, height, (int)(100*mPreview.getScaleX()), instanceId()));
     }
 
     private void transitionToCamera() {
@@ -257,24 +262,34 @@
 
         enableWindowExitAnimation(false);
 
+        final int navHeight = mInsets.bottom;
+        final int navWidth = mInsets.right;
+
         mPreview.getLocationInWindow(mTmpLoc);
         final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
         final float pvCenter = mTmpLoc[1] + pvHeight / 2f;
 
         final ViewGroup root = (ViewGroup) getRootView();
+
+        if (DEBUG) {
+            Log.d(TAG, "root = " + root.getLeft() + "," + root.getTop() + " "
+                    + root.getWidth() + "x" + root.getHeight());
+        }
+
         if (mFullscreenPreview == null) {
             mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
             mFullscreenPreview.setClickable(false);
-            root.addView(mFullscreenPreview);
+            root.addView(mFullscreenPreview, new FrameLayout.LayoutParams(
+                        root.getWidth() - navWidth,
+                        root.getHeight() - navHeight));
         }
 
-        root.getWindowVisibleDisplayFrame(mTmpRect);
-        final float fsHeight = mTmpRect.height();
-        final float fsCenter = mTmpRect.top + fsHeight / 2;
+        final float fsHeight = root.getHeight() - navHeight;
+        final float fsCenter = root.getTop() + fsHeight / 2;
 
-        final float fsScaleY = pvHeight / fsHeight;
+        final float fsScaleY = mPreview.getScaleY();
         final float fsTransY = pvCenter - fsCenter;
-        final float fsScaleX = mPreview.getScaleX();
+        final float fsScaleX = fsScaleY;
 
         mPreview.setVisibility(View.GONE);
         mFullscreenPreview.setVisibility(View.VISIBLE);
@@ -290,6 +305,36 @@
             .setDuration(WIDGET_ANIMATION_DURATION)
             .withEndAction(mPostTransitionToCameraEndAction)
             .start();
+
+        if (navHeight > 0 || navWidth > 0) {
+            final boolean atBottom = navHeight > 0;
+            if (mFakeNavBar == null) {
+                mFakeNavBar = new View(mContext);
+                mFakeNavBar.setBackgroundColor(Color.BLACK);
+                root.addView(mFakeNavBar, new FrameLayout.LayoutParams(
+                            atBottom ? FrameLayout.LayoutParams.MATCH_PARENT
+                                     : navWidth,
+                            atBottom ? navHeight
+                                     : FrameLayout.LayoutParams.MATCH_PARENT,
+                            atBottom ? Gravity.BOTTOM|Gravity.FILL_HORIZONTAL
+                                     : Gravity.RIGHT|Gravity.FILL_VERTICAL));
+                mFakeNavBar.setPivotY(navHeight);
+                mFakeNavBar.setPivotX(navWidth);
+            }
+            mFakeNavBar.setAlpha(0f);
+            if (atBottom) {
+                mFakeNavBar.setScaleY(0.5f);
+            } else {
+                mFakeNavBar.setScaleX(0.5f);
+            }
+            mFakeNavBar.setVisibility(View.VISIBLE);
+            mFakeNavBar.animate()
+                .alpha(1f)
+                .scaleY(1f)
+                .scaleY(1f)
+                .setDuration(WIDGET_ANIMATION_DURATION)
+                .start();
+        }
         mCallbacks.onLaunchingCamera();
     }
 
@@ -397,6 +442,10 @@
             mFullscreenPreview.animate().cancel();
             mFullscreenPreview.setVisibility(View.GONE);
         }
+        if (mFakeNavBar != null) {
+            mFakeNavBar.animate().cancel();
+            mFakeNavBar.setVisibility(View.GONE);
+        }
         enableWindowExitAnimation(true);
     }
 
@@ -404,6 +453,10 @@
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
                 w, h, oldw, oldh, SystemClock.uptimeMillis()));
+        if ((w != oldw && oldw > 0) || (h != oldh && oldh > 0)) {
+            // we can't trust the old geometry anymore; force a re-render
+            mRenderedSize.x = mRenderedSize.y = -1;
+        }
         mHandler.post(mRenderRunnable);
         super.onSizeChanged(w, h, oldw, oldh);
     }
@@ -454,4 +507,9 @@
     private String instanceId() {
         return Integer.toHexString(hashCode());
     }
+
+    public void setInsets(Rect insets) {
+        if (DEBUG) Log.d(TAG, "setInsets: " + insets);
+        mInsets.set(insets);
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index c4be72f..ef3d712 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -1454,6 +1454,9 @@
         mInsets.set(insets);
         if (mSlidingChallengeLayout != null) mSlidingChallengeLayout.setInsets(mInsets);
         if (mMultiPaneChallengeLayout != null) mMultiPaneChallengeLayout.setInsets(mInsets);
+
+        final CameraWidgetFrame cameraWidget = findCameraPage();
+        if (cameraWidget != null) cameraWidget.setInsets(mInsets);
     }
 
     @Override
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index c82a20e..67c455d 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -121,6 +121,12 @@
     <!-- Template for the notificaiton label for a blocked print job. [CHAR LIMIT=25] -->
     <string name="blocked_notification_title_template">Printer blocked <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
 
+    <!-- Template for the notificaiton label for a composite (multiple items) print jobs notification. [CHAR LIMIT=25] -->
+    <plurals name="composite_notification_title_template">
+        <item quantity="one"><xliff:g id="print_job_name" example="foo.jpg">%1$d</xliff:g> print job</item>
+        <item quantity="other"><xliff:g id="print_job_name" example="foo.jpg">%1$d</xliff:g> print jobs</item>
+    </plurals>
+
     <!-- Label for the notification button for cancelling a print job. [CHAR LIMIT=25] -->
     <string name="cancel">Cancel</string>
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
index 2bd0443..4aa8686 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
@@ -17,11 +17,14 @@
 package com.android.printspooler;
 
 import android.app.Notification;
+import android.app.Notification.InboxStyle;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
@@ -35,6 +38,9 @@
 import android.provider.Settings;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * This class is responsible for updating the print notifications
  * based on print job state transitions.
@@ -60,29 +66,50 @@
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
     }
 
-    public void onPrintJobStateChanged(PrintJobInfo printJob) {
-        if (DEBUG) {
-            Log.i(LOG_TAG, "onPrintJobStateChanged() printJobId: "
-                    + printJob.getId().flattenToString() + " state:"
-                    + PrintJobInfo.stateToString(printJob.getState()));
-        }
-        switch (printJob.getState()) {
-            case PrintJobInfo.STATE_QUEUED:
-            case PrintJobInfo.STATE_STARTED: {
-                createPrintingNotification(printJob);
-            } break;
+    public void onUpdateNotifications(List<PrintJobInfo> printJobs) {
+        List<PrintJobInfo> notifyPrintJobs = new ArrayList<PrintJobInfo>();
 
+        final int printJobCount = printJobs.size();
+        for (int i = 0; i < printJobCount; i++) {
+            PrintJobInfo printJob = printJobs.get(i);
+            if (shouldNotifyForState(printJob.getState())) {
+                notifyPrintJobs.add(printJob);
+            }
+        }
+
+        updateNotification(notifyPrintJobs);
+    }
+
+    private void updateNotification(List<PrintJobInfo> printJobs) {
+        if (printJobs.size() <= 0) {
+            removeNotification();
+        } else if (printJobs.size() == 1) {
+            createSimpleNotification(printJobs.get(0));
+        } else {
+            createStackedNotification(printJobs);
+        }
+    }
+
+    private void createSimpleNotification(PrintJobInfo printJob) {
+        switch (printJob.getState()) {
             case PrintJobInfo.STATE_FAILED: {
                 createFailedNotification(printJob);
             } break;
 
-            case PrintJobInfo.STATE_COMPLETED:
-            case PrintJobInfo.STATE_CANCELED: {
-                removeNotification(printJob.getId());
+            case PrintJobInfo.STATE_BLOCKED: {
+                if (!printJob.isCancelling()) {
+                    createBlockedNotification(printJob);
+                } else {
+                    createCancellingNotification(printJob);
+                }
             } break;
 
-            case PrintJobInfo.STATE_BLOCKED: {
-                createBlockedNotification(printJob);
+            default: {
+                if (!printJob.isCancelling()) {
+                    createPrintingNotification(printJob);
+                } else {
+                    createCancellingNotification(printJob);
+                }
             } break;
         }
     }
@@ -90,24 +117,22 @@
     private void createPrintingNotification(PrintJobInfo printJob) {
         Notification.Builder builder = new Notification.Builder(mContext)
                 .setContentIntent(createContentIntent(printJob.getId()))
-                .setSmallIcon(com.android.internal.R.drawable.ic_print)
-                .setContentTitle(mContext.getString(R.string.printing_notification_title_template,
-                        printJob.getLabel()))
+                .setSmallIcon(computeNotificationIcon(printJob))
+                .setContentTitle(computeNotificationTitle(printJob))
                 .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
                         createCancelIntent(printJob))
                 .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
                 .setShowWhen(true);
-        mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build());
+        mNotificationManager.notify(0, builder.build());
     }
 
     private void createFailedNotification(PrintJobInfo printJob) {
         Notification.Builder builder = new Notification.Builder(mContext)
                 .setContentIntent(createContentIntent(printJob.getId()))
-                .setSmallIcon(com.android.internal.R.drawable.ic_print_error)
-                .setContentTitle(mContext.getString(R.string.failed_notification_title_template,
-                        printJob.getLabel()))
+                .setSmallIcon(computeNotificationIcon(printJob))
+                .setContentTitle(computeNotificationTitle(printJob))
                 .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
                         createCancelIntent(printJob))
                 .addAction(R.drawable.ic_restart, mContext.getString(R.string.restart),
@@ -116,32 +141,109 @@
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
                 .setShowWhen(true);
-        mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build());
+        mNotificationManager.notify(0, builder.build());
     }
 
     private void createBlockedNotification(PrintJobInfo printJob) {
         Notification.Builder builder = new Notification.Builder(mContext)
                 .setContentIntent(createContentIntent(printJob.getId()))
-                .setSmallIcon(com.android.internal.R.drawable.ic_print_error)
-                .setContentTitle(mContext.getString(R.string.blocked_notification_title_template,
-                        printJob.getLabel()))
+                .setSmallIcon(computeNotificationIcon(printJob))
+                .setContentTitle(computeNotificationTitle(printJob))
                 .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
                         createCancelIntent(printJob))
                 .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
                 .setShowWhen(true);
-        mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build());
+           mNotificationManager.notify(0, builder.build());
     }
 
-    private void removeNotification(PrintJobId printJobId) {
-        mNotificationManager.cancel(printJobId.flattenToString(), 0);
+    private void createCancellingNotification(PrintJobInfo printJob) {
+        Notification.Builder builder = new Notification.Builder(mContext)
+                .setContentIntent(createContentIntent(printJob.getId()))
+                .setSmallIcon(computeNotificationIcon(printJob))
+                .setContentTitle(computeNotificationTitle(printJob))
+                .setContentText(printJob.getPrinterName())
+                .setWhen(System.currentTimeMillis())
+                .setOngoing(true)
+                .setShowWhen(true);
+        mNotificationManager.notify(0, builder.build());
+    }
+
+    private void createStackedNotification(List<PrintJobInfo> printJobs) {
+        Notification.Builder builder = new Notification.Builder(mContext)
+                .setContentIntent(createContentIntent(null))
+                .setWhen(System.currentTimeMillis())
+                .setOngoing(true)
+                .setShowWhen(true);
+
+        final int printJobCount = printJobs.size();
+
+        InboxStyle inboxStyle = new InboxStyle();
+        inboxStyle.setBigContentTitle(String.format(mContext.getResources().getQuantityText(
+                R.plurals.composite_notification_title_template,
+                printJobCount).toString(), printJobCount));
+
+        for (int i = printJobCount - 1; i>= 0; i--) {
+            PrintJobInfo printJob = printJobs.get(i);
+            if (i == printJobCount - 1) {
+                builder.setLargeIcon(((BitmapDrawable) mContext.getResources().getDrawable(
+                        computeNotificationIcon(printJob))).getBitmap());
+                builder.setSmallIcon(com.android.internal.R.drawable.ic_print);
+                builder.setContentTitle(computeNotificationTitle(printJob));
+                builder.setContentText(printJob.getPrinterName());
+            }
+            inboxStyle.addLine(computeNotificationTitle(printJob));
+        }
+
+        builder.setNumber(printJobCount);
+        builder.setStyle(inboxStyle);
+
+        mNotificationManager.notify(0, builder.build());
+    }
+
+    private String computeNotificationTitle(PrintJobInfo printJob) {
+        switch (printJob.getState()) {
+            case PrintJobInfo.STATE_FAILED: {
+                return mContext.getString(R.string.failed_notification_title_template,
+                        printJob.getLabel());
+            }
+
+            case PrintJobInfo.STATE_BLOCKED: {
+                if (!printJob.isCancelling()) {
+                    return mContext.getString(R.string.blocked_notification_title_template,
+                            printJob.getLabel());
+                } else {
+                    return mContext.getString(
+                            R.string.cancelling_notification_title_template,
+                            printJob.getLabel());
+                }
+            }
+
+            default: {
+                if (!printJob.isCancelling()) {
+                    return mContext.getString(R.string.printing_notification_title_template,
+                            printJob.getLabel());
+                } else {
+                    return mContext.getString(
+                            R.string.cancelling_notification_title_template,
+                            printJob.getLabel());
+                }
+            }
+        }
+    }
+
+    private void removeNotification() {
+        mNotificationManager.cancel(0);
     }
 
     private PendingIntent createContentIntent(PrintJobId printJobId) {
         Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS);
-        intent.putExtra(EXTRA_PRINT_JOB_ID, printJobId.flattenToString());
-        return PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+        if (printJobId != null) {
+            intent.putExtra(EXTRA_PRINT_JOB_ID, printJobId.flattenToString());
+            intent.setData(Uri.fromParts("printjob", printJobId.flattenToString(), null));
+        }
+        return PendingIntent.getActivity(mContext, 0, intent, 0);
     }
 
     private PendingIntent createCancelIntent(PrintJobInfo printJob) {
@@ -160,6 +262,36 @@
         return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
     }
 
+    private static boolean shouldNotifyForState(int state) {
+        switch (state) {
+            case PrintJobInfo.STATE_QUEUED:
+            case PrintJobInfo.STATE_STARTED:
+            case PrintJobInfo.STATE_FAILED:
+            case PrintJobInfo.STATE_COMPLETED:
+            case PrintJobInfo.STATE_CANCELED:
+            case PrintJobInfo.STATE_BLOCKED: {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static int computeNotificationIcon(PrintJobInfo printJob) {
+        switch (printJob.getState()) {
+            case PrintJobInfo.STATE_FAILED:
+            case PrintJobInfo.STATE_BLOCKED: {
+                return com.android.internal.R.drawable.ic_print_error;
+            }
+            default: {
+                if (!printJob.isCancelling()) {
+                    return com.android.internal.R.drawable.ic_print;
+                } else {
+                    return R.drawable.stat_notify_cancelling;
+                }
+            }
+        }
+    }
+
     public static final class NotificationBroadcastReceiver extends BroadcastReceiver {
         private static final String LOG_TAG = "NotificationBroadcastReceiver";
 
@@ -183,20 +315,6 @@
                 Log.i(LOG_TAG, "handleCancelPrintJob() printJobId:" + printJobId);
             }
 
-            // Put up a notification that we are trying to cancel.
-            NotificationManager notificationManager = (NotificationManager)
-                    context.getSystemService(Context.NOTIFICATION_SERVICE);
-            Notification.Builder builder = new Notification.Builder(context)
-                    .setSmallIcon(R.drawable.stat_notify_cancelling)
-                    .setContentTitle(context.getString(
-                            R.string.cancelling_notification_title_template,
-                            printJobLabel))
-                    .setContentText(printerName)
-                    .setWhen(System.currentTimeMillis())
-                    .setOngoing(true)
-                    .setShowWhen(true);
-            notificationManager.notify(printJobId.flattenToString(), 0, builder.build());
-
             // Call into the print manager service off the main thread since
             // the print manager service may end up binding to the print spooler
             // service which binding is handled on the main thread.
@@ -217,8 +335,8 @@
                     // done on another thread and until it finishes the spooler has
                     // to be kept around.
                     try {
-                    IPrintManager printManager = IPrintManager.Stub.asInterface(
-                            ServiceManager.getService(Context.PRINT_SERVICE));
+                        IPrintManager printManager = IPrintManager.Stub.asInterface(
+                                ServiceManager.getService(Context.PRINT_SERVICE));
                         printManager.cancelPrintJob(printJobId, PrintManager.APP_ID_ANY,
                                 UserHandle.myUserId());
                     } catch (RemoteException re) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 0bd8344..d6ebc2d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -456,6 +456,7 @@
                 // Then update the print jobs's pages as we will not do a write
                 // and we usually update the pages in the write complete callback.
                 updatePrintJobPages(mDocument.pages, mRequestedPages);
+                mEditor.updateUi();
                 if (mEditor.isDone()) {
                     requestCreatePdfFileOrFinish();
                 }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index d1b42bc..e1ddb40 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -230,6 +230,11 @@
             protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
                 PrintSpoolerService.this.dump(fd, writer, args);
             }
+
+            @Override
+            public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
+                PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling);
+            }
         };
     }
 
@@ -459,8 +464,6 @@
                 fileForJobMap.remove(printJob.getId());
             }
 
-            // Update the notification.
-            mNotificationController.onPrintJobStateChanged(printJob);
             switch (printJob.getState()) {
                 case PrintJobInfo.STATE_QUEUED:
                 case PrintJobInfo.STATE_STARTED:
@@ -475,6 +478,11 @@
             }
         }
 
+        if (!mPrintJobs.isEmpty()) {
+            // Update the notification.
+            mNotificationController.onUpdateNotifications(mPrintJobs);
+        }
+
         // Delete the orphan files.
         if (fileForJobMap != null) {
             final int orphanFileCount = fileForJobMap.size();
@@ -586,7 +594,7 @@
 
                 printJob.setState(state);
                 printJob.setStateReason(error);
-                mNotificationController.onPrintJobStateChanged(printJob);
+                printJob.setCancelling(false);
 
                 if (DEBUG_PRINT_JOB_LIFECYCLE) {
                     Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
@@ -626,6 +634,8 @@
                         HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
                         printJob);
                 mHandlerCaller.executeOrSendMessage(message);
+
+                mNotificationController.onUpdateNotifications(mPrintJobs);
             }
         }
 
@@ -694,6 +704,24 @@
         return false;
     }
 
+    public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                printJob.setCancelling(cancelling);
+                if (shouldPersistPrintJob(printJob)) {
+                    mPersistanceManager.writeStateLocked();
+                }
+                mNotificationController.onUpdateNotifications(mPrintJobs);
+
+                Message message = mHandlerCaller.obtainMessageO(
+                        HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
+                        printJob);
+                mHandlerCaller.executeOrSendMessage(message);
+            }
+        }
+    }
+
     public void setPrintJobCopiesNoPersistence(PrintJobId printJobId, int copies) {
         synchronized (mLock) {
             PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
@@ -783,6 +811,7 @@
         private static final String ATTR_COPIES = "copies";
         private static final String ATTR_PRINTER_NAME = "printerName";
         private static final String ATTR_STATE_REASON = "stateReason";
+        private static final String ATTR_CANCELLING = "cancelling";
 
         private static final String TAG_MEDIA_SIZE = "mediaSize";
         private static final String TAG_RESOLUTION = "resolution";
@@ -881,6 +910,8 @@
                     if (!TextUtils.isEmpty(stateReason)) {
                         serializer.attribute(null, ATTR_STATE_REASON, stateReason);
                     }
+                    serializer.attribute(null, ATTR_CANCELLING, String.valueOf(
+                            printJob.isCancelling()));
 
                     PrinterId printerId = printJob.getPrinterId();
                     if (printerId != null) {
@@ -1073,6 +1104,9 @@
             printJob.setPrinterName(printerName);
             String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON);
             printJob.setStateReason(stateReason);
+            String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING);
+            printJob.setCancelling(!TextUtils.isEmpty(cancelling)
+                    ? Boolean.parseBoolean(cancelling) : false);
 
             parser.next();
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
index 7a91cef..d688932 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -168,6 +168,14 @@
     }
 
     @Override
+    public void onPause() {
+        if (mAnnounceFilterResult != null) {
+            mAnnounceFilterResult.remove();
+        }
+        super.onPause();
+    }
+
+    @Override
     public void onListItemClick(ListView list, View view, int position, long id) {
         PrinterInfo printer = (PrinterInfo) list.getAdapter().getItem(position);
         Activity activity = getActivity();
@@ -266,11 +274,13 @@
         }
     }
 
-    private void announceSearchResult() {
-        if (mAnnounceFilterResult == null) {
-            mAnnounceFilterResult = new AnnounceFilterResult();
+    private void announceSearchResultIfNeeded() {
+        if (AccessibilityManager.getInstance(getActivity()).isEnabled()) {
+            if (mAnnounceFilterResult == null) {
+                mAnnounceFilterResult = new AnnounceFilterResult();
+            }
+            mAnnounceFilterResult.post();
         }
-        mAnnounceFilterResult.post();
     }
 
     public static class AddPrinterAlertDialogFragment extends DialogFragment {
@@ -397,7 +407,7 @@
                         resultCountChanged = (oldPrinterCount != mFilteredPrinters.size());
                     }
                     if (resultCountChanged) {
-                        announceSearchResult();
+                        announceSearchResultIfNeeded();
                     }
                     notifyDataSetChanged();
                 }
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png
deleted file mode 100644
index f82a037..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png
deleted file mode 100644
index ed6c0db..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png
deleted file mode 100644
index e28c06a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/nav_background.9.png b/packages/SystemUI/res/drawable-hdpi/nav_background.9.png
index db36d2b..a09e654 100644
--- a/packages/SystemUI/res/drawable-hdpi/nav_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/nav_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
index 9befc34..d43d1dc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png
deleted file mode 100644
index 3073986..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png
deleted file mode 100644
index 2a0bc59..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png
deleted file mode 100644
index 9b1cc58..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/nav_background.9.png b/packages/SystemUI/res/drawable-mdpi/nav_background.9.png
index 45e6e8f..aa74153 100644
--- a/packages/SystemUI/res/drawable-mdpi/nav_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/nav_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
index 2e24f6f..61d7511 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png
deleted file mode 100644
index 72c587d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png
deleted file mode 100644
index d18dbd9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png
deleted file mode 100644
index 31230af..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png b/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png
index 152e4ac..3b52195 100644
--- a/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
index a7f0017..192d3f7 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_circle.png
deleted file mode 100644
index 849d547..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_circle.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_hour.png
deleted file mode 100644
index 57dd8a6..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_hour.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_minute.png
deleted file mode 100644
index a9b8ba5..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_minute.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png b/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png
index cce2e062..b35183c 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
index ad34d49..1e5f15f 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_time.xml b/packages/SystemUI/res/layout/quick_settings_tile_time.xml
deleted file mode 100644
index 910e1f6..0000000
--- a/packages/SystemUI/res/layout/quick_settings_tile_time.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:orientation="vertical">
-    <AnalogClock
-        android:id="@+id/analog_clock"
-        android:layout_width="32dp"
-        android:layout_height="32dp"
-        android:layout_gravity="center"
-        android:layout_marginBottom="10dp"
-        android:dial="@drawable/ic_qs_clock_circle"
-        android:hand_hour="@drawable/ic_qs_clock_hour"
-        android:hand_minute="@drawable/ic_qs_clock_minute"
-        />
-    <com.android.systemui.statusbar.policy.DateView
-        android:textAppearance="@style/TextAppearance.QuickSettings.TileView"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:gravity="center"
-        />
-</LinearLayout>
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 33edd72..5423bb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -358,26 +358,6 @@
         parent.addView(brightnessTile);
         mDynamicSpannedTiles.add(brightnessTile);
 
-        // Time tile
-        /*
-        QuickSettingsTileView timeTile = (QuickSettingsTileView)
-                inflater.inflate(R.layout.quick_settings_tile, parent, false);
-        timeTile.setContent(R.layout.quick_settings_tile_time, inflater);
-        timeTile.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                // Quick. Clock. Quick. Clock. Quick. Clock.
-                startSettingsActivity(Intent.ACTION_QUICK_CLOCK);
-            }
-        });
-        mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() {
-            @Override
-            public void refreshView(QuickSettingsTileView view, State alarmState) {}
-        });
-        parent.addView(timeTile);
-        mDynamicSpannedTiles.add(timeTile);
-        */
-
         // Settings tile
         final QuickSettingsBasicTile settingsTile = new QuickSettingsBasicTile(mContext);
         settingsTile.setImageResource(R.drawable.ic_qs_settings);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 9d0418d..e6823ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -34,6 +34,7 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -308,6 +309,7 @@
         refreshBluetoothTile();
         refreshBrightnessTile();
         refreshRotationLockTile();
+        refreshRssiTile();
     }
 
     // Settings
@@ -501,6 +503,14 @@
         }
     }
 
+    void refreshRssiTile() {
+        if (mRSSITile != null) {
+            // We reinflate the original view due to potential styling changes that may have
+            // taken place due to a configuration change.
+            mRSSITile.reinflateContent(LayoutInflater.from(mContext));
+        }
+    }
+
     // Bluetooth
     void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) {
         mBluetoothTile = view;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java
index 9cff242..3d520f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
@@ -26,13 +27,16 @@
  *
  */
 class QuickSettingsTileView extends FrameLayout {
+    private static final String TAG = "QuickSettingsTileView";
 
+    private int mContentLayoutId;
     private int mColSpan;
     private int mRowSpan;
 
     public QuickSettingsTileView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        mContentLayoutId = -1;
         mColSpan = 1;
         mRowSpan = 1;
     }
@@ -46,9 +50,19 @@
     }
 
     void setContent(int layoutId, LayoutInflater inflater) {
+        mContentLayoutId = layoutId;
         inflater.inflate(layoutId, this);
     }
 
+    void reinflateContent(LayoutInflater inflater) {
+        if (mContentLayoutId != -1) {
+            removeAllViews();
+            setContent(mContentLayoutId, inflater);
+        } else {
+            Log.e(TAG, "Not reinflating content: No layoutId set");
+        }
+    }
+
     @Override
     public void setVisibility(int vis) {
         if (QuickSettings.DEBUG_GONE_TILES) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e9e3b27..225bb94 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2992,7 +2992,7 @@
             pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
             pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
             // IM dock windows layout below the nav bar...
-            pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
+            pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
             // ...with content insets above the nav bar
             cf.bottom = vf.bottom = mStableBottom;
             // IM dock windows always go to the bottom of the screen.
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
index d2d5280..546324a 100644
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -766,13 +766,17 @@
                 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
                 {
                     IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
-                    mStateChangeCallbacks.register(callback);
+                    if (callback != null) {
+                        mStateChangeCallbacks.register(callback);
+                    }
                     break;
                 }
                 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
                 {
                     IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
-                    mStateChangeCallbacks.unregister(callback);
+                    if (callback != null) {
+                        mStateChangeCallbacks.unregister(callback);
+                    }
                     break;
                 }
                 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 5695ee5..70418e8 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -353,6 +353,11 @@
      */
     private static final int EVENT_SAMPLE_INTERVAL_ELAPSED = 15;
 
+    /**
+     * PAC manager has received new port.
+     */
+    private static final int EVENT_PROXY_HAS_CHANGED = 16;
+
     /** Handler used for internal events. */
     private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -679,7 +684,7 @@
                 },
                 new IntentFilter(filter));
 
-        mPacManager = new PacManager(mContext);
+        mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
 
         filter = new IntentFilter();
         filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
@@ -3124,6 +3129,10 @@
                     handleNetworkSamplingTimeout();
                     break;
                 }
+                case EVENT_PROXY_HAS_CHANGED: {
+                    handleApplyDefaultProxy((ProxyProperties)msg.obj);
+                    break;
+                }
             }
         }
     }
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 1b8876d..a99b58a 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -736,9 +736,9 @@
                         + "there is at least one pointer down!");
             }
             case MotionEvent.ACTION_UP: {
+                mAms.onTouchInteractionEnd();
                 // Announce the end of a the touch interaction.
                 sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
-                mAms.onTouchInteractionEnd();
                 mLongPressingPointerId = -1;
                 mLongPressingPointerDeltaX = 0;
                 mLongPressingPointerDeltaY = 0;
@@ -822,6 +822,7 @@
         AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
         if (accessibilityManager.isEnabled()) {
             AccessibilityEvent event = AccessibilityEvent.obtain(type);
+            event.setWindowId(mAms.getActiveWindowId());
             accessibilityManager.sendAccessibilityEvent(event);
             switch (type) {
                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f7b7515..4fbbb78 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7555,7 +7555,7 @@
                         // Use existing process if already started
                         ProcessRecord proc = getProcessRecordLocked(
                                 cpi.processName, cpr.appInfo.uid, false);
-                        if (proc != null) {
+                        if (proc != null && proc.thread != null) {
                             if (DEBUG_PROVIDER) {
                                 Slog.d(TAG, "Installing in existing process " + proc);
                             }
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index 1cb2fe3..837fb05 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -27,6 +27,7 @@
 import android.net.Proxy;
 import android.net.ProxyProperties;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -89,6 +90,9 @@
     private boolean mHasSentBroadcast;
     private boolean mHasDownloaded;
 
+    private Handler mConnectivityHandler;
+    private int mProxyMessage;
+
     /**
      * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
      */
@@ -128,7 +132,7 @@
         }
     }
 
-    public PacManager(Context context) {
+    public PacManager(Context context, Handler handler, int proxyMessage) {
         mContext = context;
         mLastPort = -1;
 
@@ -136,6 +140,8 @@
                 context, 0, new Intent(ACTION_PAC_REFRESH), 0);
         context.registerReceiver(new PacRefreshIntentReceiver(),
                 new IntentFilter(ACTION_PAC_REFRESH));
+        mConnectivityHandler = handler;
+        mProxyMessage = proxyMessage;
     }
 
     private AlarmManager getAlarmManager() {
@@ -156,6 +162,10 @@
      */
     public synchronized boolean setCurrentProxyScriptUrl(ProxyProperties proxy) {
         if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
+            if (proxy.getPacFileUrl().equals(mPacUrl)) {
+                // Allow to send broadcast, nothing to do.
+                return false;
+            }
             synchronized (mProxyLock) {
                 mPacUrl = proxy.getPacFileUrl();
             }
@@ -356,16 +366,7 @@
     }
 
     private void sendPacBroadcast(ProxyProperties proxy) {
-        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
-        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
-            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
+        mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy));
     }
 
     private synchronized void sendProxyIfNeeded() {
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index 798cea3..4866f57 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -255,6 +255,31 @@
         return false;
     }
 
+    public final void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().setPrintJobCancelling(printJobId,
+                    cancelling);
+        } catch (RemoteException re) {
+            Slog.e(LOG_TAG, "Error setting print job cancelling.", re);
+        } catch (TimeoutException te) {
+            Slog.e(LOG_TAG, "Error setting print job cancelling.", te);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+                        + "] setPrintJobCancelling()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
     public final void removeObsoletePrintJobs() {
         throwIfCalledOnMainThread();
         synchronized (mLock) {
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index b3f0036..b6c7853 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -240,6 +240,10 @@
         if (printJobInfo == null) {
             return;
         }
+
+        // Take a note that we are trying to cancel the job.
+        mSpooler.setPrintJobCancelling(printJobId, true);
+
         if (printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
             ComponentName printServiceName = printJobInfo.getPrinterId().getServiceName();
             RemotePrintService printService = null;