Merge "PackageManager#queryIntentServices breaks its contract." into klp-dev
diff --git a/Android.mk b/Android.mk
index 14d1a02..13b717a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -166,6 +166,7 @@
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
 	core/java/android/print/IPrintClient.aidl \
+	core/java/android/print/IPrintJobStateChangeListener.aidl \
 	core/java/android/print/IPrintManager.aidl \
 	core/java/android/print/IPrintSpooler.aidl \
 	core/java/android/print/IPrintSpoolerCallbacks.aidl \
diff --git a/api/current.txt b/api/current.txt
index c2dfa92..4f398cf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19372,6 +19372,13 @@
     method public void cancel();
     method public android.print.PrintJobId getId();
     method public android.print.PrintJobInfo getInfo();
+    method public boolean isBlocked();
+    method public boolean isCancelled();
+    method public boolean isCompleted();
+    method public boolean isFailed();
+    method public boolean isQueued();
+    method public boolean isStarted();
+    method public void restart();
   }
 
   public final class PrintJobId implements android.os.Parcelable {
@@ -19384,6 +19391,7 @@
     method public int describeContents();
     method public android.print.PrintAttributes getAttributes();
     method public int getCopies();
+    method public long getCreationTime();
     method public android.print.PrintJobId getId();
     method public java.lang.String getLabel();
     method public android.print.PageRange[] getPages();
@@ -20970,6 +20978,7 @@
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
     method public static java.lang.String getRootId(android.net.Uri);
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
+    method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_INFO = "info";
     field public static final java.lang.String EXTRA_LOADING = "loading";
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index fc277f1..30bffc4 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -550,8 +550,8 @@
      * fixed depth of field range
      * </p>
      */
-    public static final Key<Float> LENS_FOCUS_RANGE =
-            new Key<Float>("android.lens.focusRange", float.class);
+    public static final Key<float[]> LENS_FOCUS_RANGE =
+            new Key<float[]>("android.lens.focusRange", float[].class);
 
     /**
      * <p>
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index d0feaa3..d7ef4bc 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -159,7 +159,7 @@
                         com.android.internal.R.styleable.OffHostApduService_description);
                 mRequiresDeviceUnlock = false;
                 mBannerResourceId = sa.getResourceId(
-                        com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
+                        com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1);
                 sa.recycle();
             }
 
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 0a1ffc9..ea9fd06 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -158,7 +158,7 @@
         public int otherSharedClean;
 
         /** @hide */
-        public static final int NUM_OTHER_STATS = 14;
+        public static final int NUM_OTHER_STATS = 16;
 
         /** @hide */
         public static final int NUM_DVK_STATS = 5;
@@ -285,12 +285,14 @@
                 case 10: return "code mmap";
                 case 11: return "image mmap";
                 case 12: return "Other mmap";
-                case 13: return "GPU";
-                case 14: return ".Heap";
-                case 15: return ".LOS";
-                case 16: return ".LinearAlloc";
-                case 17: return ".GC";
-                case 18: return ".JITCache";
+                case 13: return "Graphics";
+                case 14: return "GL";
+                case 15: return "Other memtrack";
+                case 16: return ".Heap";
+                case 17: return ".LOS";
+                case 18: return ".LinearAlloc";
+                case 19: return ".GC";
+                case 20: return ".JITCache";
                 default: return "????";
             }
         }
diff --git a/core/java/android/print/IPrintJobStateChangeListener.aidl b/core/java/android/print/IPrintJobStateChangeListener.aidl
new file mode 100644
index 0000000..c1d39f0
--- /dev/null
+++ b/core/java/android/print/IPrintJobStateChangeListener.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.print;
+
+import android.print.PrintJobId;
+
+/**
+ * Interface for observing print job state changes.
+ *
+ * @hide
+ */
+oneway interface IPrintJobStateChangeListener {
+    void onPrintJobStateChanged(in PrintJobId printJobId);
+}
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl
index 4e839c6..4044b31 100644
--- a/core/java/android/print/IPrintManager.aidl
+++ b/core/java/android/print/IPrintManager.aidl
@@ -20,6 +20,7 @@
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintClient;
 import android.print.PrintJobId;
+import android.print.IPrintJobStateChangeListener;
 import android.print.PrinterId;
 import android.print.PrintJobInfo;
 import android.print.PrintAttributes;
@@ -39,6 +40,11 @@
     void cancelPrintJob(in PrintJobId printJobId, int appId, int userId);
     void restartPrintJob(in PrintJobId printJobId, int appId, int userId);
 
+    void addPrintJobStateChangeListener(in IPrintJobStateChangeListener listener,
+            int appId, int userId);
+    void removePrintJobStateChangeListener(in IPrintJobStateChangeListener listener,
+            int userId);
+
     List<PrintServiceInfo> getEnabledPrintServices(int userId);
 
     void createPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, int userId);
diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl
index 8b511d6..0cf00cc 100644
--- a/core/java/android/print/IPrintSpoolerClient.aidl
+++ b/core/java/android/print/IPrintSpoolerClient.aidl
@@ -18,7 +18,7 @@
 
 import android.content.ComponentName;
 import android.print.PrintJobInfo;
-
+import android.print.PrintJobId;
 
 /**
  * Interface for receiving interesting state updates from the print spooler.
@@ -29,4 +29,5 @@
     void onPrintJobQueued(in PrintJobInfo printJob);
     void onAllPrintJobsForServiceHandled(in ComponentName printService);
     void onAllPrintJobsHandled();
+    void onPrintJobStateChanged(in PrintJobId printJobId, int appId);
 }
diff --git a/core/java/android/print/PrintJob.java b/core/java/android/print/PrintJob.java
index 00ade07..535ae43 100644
--- a/core/java/android/print/PrintJob.java
+++ b/core/java/android/print/PrintJob.java
@@ -62,14 +62,110 @@
     }
 
     /**
-     * Cancels this print job.
+     * Cancels this print job. You can request cancellation of a
+     * queued, started, blocked, or failed print job.
+     *
+     * @see #isQueued()
+     * @see #isStarted()
+     * @see #isBlocked()
+     * @see #isFailed()
      */
     public void cancel() {
-        if (!isInImmutableState()) {
+        final int state = getInfo().getState();
+        if (state == PrintJobInfo.STATE_QUEUED
+                || state == PrintJobInfo.STATE_STARTED
+                || state == PrintJobInfo.STATE_BLOCKED
+                || state == PrintJobInfo.STATE_FAILED) {
             mPrintManager.cancelPrintJob(mCachedInfo.getId());
         }
     }
 
+    /**
+     * Restarts this print job. You can request restart of a failed
+     * print job.
+     *
+     * @see #isFailed()
+     */
+    public void restart() {
+        if (isFailed()) {
+            mPrintManager.restartPrintJob(mCachedInfo.getId());
+        }
+    }
+
+    /**
+     * Gets whether this print job is queued. Such a print job is
+     * ready to be printed. You can request a cancellation via
+     * {@link #cancel()}.
+     *
+     * @return Whether the print job is queued.
+     *
+     * @see #cancel()
+     */
+    public boolean isQueued() {
+        return getInfo().getState() == PrintJobInfo.STATE_QUEUED;
+    }
+
+    /**
+     * Gets whether this print job is started. Such a print job is
+     * being printed. You can request a cancellation via
+     * {@link #cancel()}.
+     *
+     * @return Whether the print job is started.
+     *
+     * @see #cancel()
+     */
+    public boolean isStarted() {
+        return getInfo().getState() == PrintJobInfo.STATE_STARTED;
+    }
+
+    /**
+     * Gets whether this print job is blocked. Such a print job is halted
+     * due to an abnormal condition. You can request a cancellation via
+     * {@link #cancel()}.
+     *
+     * @return Whether the print job is blocked.
+     *
+     * @see #cancel()
+     */
+    public boolean isBlocked() {
+        return getInfo().getState() == PrintJobInfo.STATE_BLOCKED;
+    }
+
+    /**
+     * Gets whether this print job is completed. Such a print job
+     * is successfully printed. You can neither cancel nor restart
+     * such a print job.
+     *
+     * @return Whether the print job is completed.
+     */
+    public boolean isCompleted() {
+        return getInfo().getState() == PrintJobInfo.STATE_COMPLETED;
+    }
+
+    /**
+     * Gets whether this print job is failed. Such a print job is
+     * not successfully printed due to an error. You can request
+     * a restart via {@link #restart()}.
+     *
+     * @return Whether the print job is failed.
+     *
+     * @see #restart()
+     */
+    public boolean isFailed() {
+        return getInfo().getState() == PrintJobInfo.STATE_FAILED;
+    }
+
+    /**
+     * Gets whether this print job is cancelled. Such a print job was
+     * cancelled as a result of a user request. This is a final state.
+     * You cannot restart such a print job.
+     *
+     * @return Whether the print job is cancelled.
+     */
+    public boolean isCancelled() {
+        return getInfo().getState() == PrintJobInfo.STATE_CANCELED;
+    }
+
     private boolean isInImmutableState() {
         final int state = mCachedInfo.getState();
         return state == PrintJobInfo.STATE_COMPLETED
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 502a9f2..e5d06a2 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -138,6 +138,9 @@
     /** Optional tag assigned by a print service.*/
     private String mTag;
 
+    /** The wall time when the print job was created. */
+    private long mCreationTime;
+
     /** How many copies to print. */
     private int mCopies;
 
@@ -168,6 +171,7 @@
         mAppId = other.mAppId;
         mUserId = other.mUserId;
         mTag = other.mTag;
+        mCreationTime = other.mCreationTime;
         mCopies = other.mCopies;
         mStateReason = other.mStateReason;
         mPageRanges = other.mPageRanges;
@@ -184,6 +188,7 @@
         mAppId = parcel.readInt();
         mUserId = parcel.readInt();
         mTag = parcel.readString();
+        mCreationTime = parcel.readLong();
         mCopies = parcel.readInt();
         mStateReason = parcel.readString();
         if (parcel.readInt() == 1) {
@@ -368,6 +373,29 @@
     }
 
     /**
+     * Gets the wall time in millisecond when this print job was created.
+     *
+     * @return The creation time in milliseconds.
+     */
+    public long getCreationTime() {
+        return mCreationTime;
+    }
+
+    /**
+     * Sets the wall time in milliseconds when this print job was created.
+     *
+     * @param creationTime The creation time in milliseconds.
+     *
+     * @hide
+     */
+    public void setCreationTime(long creationTime) {
+        if (creationTime < 0) {
+            throw new IllegalArgumentException("creationTime must be non-negative.");
+        }
+        mCreationTime = creationTime;
+    }
+
+    /**
      * Gets the number of copies.
      *
      * @return The number of copies or zero if not set.
@@ -491,6 +519,7 @@
         parcel.writeInt(mAppId);
         parcel.writeInt(mUserId);
         parcel.writeString(mTag);
+        parcel.writeLong(mCreationTime);
         parcel.writeInt(mCopies);
         parcel.writeString(mStateReason);
         if (mPageRanges != null) {
@@ -522,6 +551,7 @@
         builder.append(", status: ").append(stateToString(mState));
         builder.append(", printer: " + mPrinterId);
         builder.append(", tag: ").append(mTag);
+        builder.append(", creationTime: " + mCreationTime);
         builder.append(", copies: ").append(mCopies);
         builder.append(", attributes: " + (mAttributes != null
                 ? mAttributes.toString() : null));
@@ -537,7 +567,7 @@
     public static String stateToString(int state) {
         switch (state) {
             case STATE_CREATED: {
-                return "STATUS_CREATED";
+                return "STATE_CREATED";
             }
             case STATE_QUEUED: {
                 return "STATE_QUEUED";
@@ -546,21 +576,20 @@
                 return "STATE_STARTED";
             }
             case STATE_FAILED: {
-                return "STATUS_FAILED";
+                return "STATE_FAILED";
             }
             case STATE_COMPLETED: {
-                return "STATUS_COMPLETED";
+                return "STATE_COMPLETED";
             }
             case STATE_CANCELED: {
-                return "STATUS_CANCELED";
+                return "STATE_CANCELED";
             }
             default: {
-                return "STATUS_UNKNOWN";
+                return "STATE_UNKNOWN";
             }
         }
     }
 
-
     public static final Parcelable.Creator<PrintJobInfo> CREATOR =
             new Creator<PrintJobInfo>() {
         @Override
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 5429155..a015388 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -30,6 +30,7 @@
 import android.print.PrintDocumentAdapter.WriteResultCallback;
 import android.printservice.PrintServiceInfo;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.internal.os.SomeArgs;
@@ -40,6 +41,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * System level service for accessing the printing capabilities of the platform.
@@ -70,6 +72,19 @@
 
     private final Handler mHandler;
 
+    private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> mPrintJobStateChangeListeners;
+
+    /** @hide */
+    public interface PrintJobStateChangeListener {
+
+        /**
+         * Callback notifying that a print job state changed.
+         *
+         * @param printJobId The print job id.
+         */
+        public void onPrintJobsStateChanged(PrintJobId printJobId);
+    }
+
     /**
      * Creates a new instance.
      *
@@ -106,7 +121,6 @@
      * @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.
-     *
      * @hide
      */
     public PrintManager getGlobalPrintManagerForUser(int userId) {
@@ -123,6 +137,75 @@
     }
 
     /**
+     * Adds a listener for observing the state of print jobs.
+     *
+     * @param listener The listener to add.
+     *
+     * @hide
+     */
+    public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
+        if (mPrintJobStateChangeListeners == null) {
+            mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener,
+                    PrintJobStateChangeListenerWrapper>();
+        }
+        PrintJobStateChangeListenerWrapper wrappedListener =
+                new PrintJobStateChangeListenerWrapper(listener);
+        try {
+            mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId);
+            mPrintJobStateChangeListeners.put(listener, wrappedListener);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error adding print job state change listener", re);
+        }
+    }
+
+    /**
+     * Removes a listener for observing the state of print jobs.
+     *
+     * @param listener The listener to remove.
+     *
+     * @hide
+     */
+    public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
+        if (mPrintJobStateChangeListeners == null) {
+            return;
+        }
+        PrintJobStateChangeListenerWrapper wrappedListener =
+                mPrintJobStateChangeListeners.remove(listener);
+        if (wrappedListener == null) {
+            return;
+        }
+        if (mPrintJobStateChangeListeners.isEmpty()) {
+            mPrintJobStateChangeListeners = null;
+        }
+        try {
+            mService.removePrintJobStateChangeListener(wrappedListener, mUserId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error removing print job state change listener", re);
+        }
+    }
+
+    /**
+     * Gets a print job given its id.
+     *
+     * @return The print job list.
+     *
+     * @see PrintJob
+     *
+     * @hide
+     */
+    public PrintJob getPrintJob(PrintJobId printJobId) {
+        try {
+            PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId);
+            if (printJob != null) {
+                return new PrintJob(printJob, this);
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error getting print job", re);
+        }
+        return null;
+    }
+
+    /**
      * Gets the print jobs for this application.
      *
      * @return The print job list.
@@ -155,6 +238,14 @@
         }
     }
 
+    void restartPrintJob(PrintJobId printJobId) {
+        try {
+            mService.restartPrintJob(printJobId, mAppId, mUserId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error restarting a print job: " + printJobId, re);
+        }
+    }
+
     /**
      * Creates a print job for printing a {@link PrintDocumentAdapter} with default print
      * attributes.
@@ -163,7 +254,6 @@
      * @param documentAdapter An adapter that emits the document to print.
      * @param attributes The default print job attributes.
      * @return The created print job on success or null on failure.
-     *
      * @see PrintJob
      */
     public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter,
@@ -220,11 +310,11 @@
         }
 
         @Override
-        public void startPrintJobConfigActivity(IntentSender intent)  {
+        public void startPrintJobConfigActivity(IntentSender intent) {
             PrintManager manager = mWeakPrintManager.get();
             if (manager != null) {
                 SomeArgs args = SomeArgs.obtain();
-                args.arg1 =  manager.mContext;
+                args.arg1 = manager.mContext;
                 args.arg2 = intent;
                 manager.mHandler.obtainMessage(0, args).sendToTarget();
             }
@@ -271,7 +361,7 @@
 
         @Override
         public void write(PageRange[] pages, ParcelFileDescriptor fd,
-            IWriteResultCallback callback, int sequence) {
+                IWriteResultCallback callback, int sequence) {
             synchronized (mLock) {
                 if (mLayoutOrWriteCancellation != null) {
                     mLayoutOrWriteCancellation.cancel();
@@ -492,4 +582,21 @@
             }
         }
     }
+
+    private static final class PrintJobStateChangeListenerWrapper extends
+            IPrintJobStateChangeListener.Stub {
+        private final WeakReference<PrintJobStateChangeListener> mWeakListener;
+
+        public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener) {
+            mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener);
+        }
+
+        @Override
+        public void onPrintJobStateChanged(PrintJobId printJobId) {
+            PrintJobStateChangeListener listener = mWeakListener.get();
+            if (listener != null) {
+                listener.onPrintJobsStateChanged(printJobId);
+            }
+        }
+    }
 }
diff --git a/core/java/android/print/PrinterInfo.java b/core/java/android/print/PrinterInfo.java
index a51e28b..ad79a38 100644
--- a/core/java/android/print/PrinterInfo.java
+++ b/core/java/android/print/PrinterInfo.java
@@ -302,7 +302,7 @@
 
         private boolean isValidStatus(int status) {
             return (status == STATUS_IDLE
-                    || status == STATUS_IDLE
+                    || status == STATUS_BUSY
                     || status == STATUS_UNAVAILABLE);
         }
     }
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index 2fcae6b..721e31e 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -175,7 +175,7 @@
      */
     public boolean isCancelled() {
         PrintService.throwIfNotCalledOnMainThread();
-        return getInfo().getState() == PrintJobInfo.STATE_FAILED;
+        return getInfo().getState() == PrintJobInfo.STATE_CANCELED;
     }
 
     /**
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 8f22312..4c9af19 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -21,7 +21,10 @@
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -573,6 +576,28 @@
     }
 
     /**
+     * Test if the given Uri represents a {@link Document} backed by a
+     * {@link DocumentsProvider}.
+     */
+    public static boolean isDocumentUri(Context context, Uri uri) {
+        final List<String> paths = uri.getPathSegments();
+        if (paths.size() < 2) {
+            return false;
+        }
+        if (!PATH_DOCUMENT.equals(paths.get(0))) {
+            return false;
+        }
+
+        final ProviderInfo info = context.getPackageManager()
+                .resolveContentProvider(uri.getAuthority(), PackageManager.GET_META_DATA);
+        if (info.metaData != null && info.metaData.containsKey(
+                DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Extract the {@link Root#COLUMN_ROOT_ID} from the given Uri.
      */
     public static String getRootId(Uri rootUri) {
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index a327adc..a54b364 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -66,4 +66,16 @@
             throw new IllegalStateException();
         }
     }
+
+    /**
+     * Check the requested flags, throwing if any requested flags are outside
+     * the allowed set.
+     */
+    public static void checkFlagsArgument(int requestedFlags, int allowedFlags) {
+        if ((requestedFlags & allowedFlags) != requestedFlags) {
+            throw new IllegalArgumentException("Requested flags 0x"
+                    + Integer.toHexString(requestedFlags) + ", but only 0x"
+                    + Integer.toHexString(allowedFlags) + " are allowed");
+        }
+    }
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f78d807..e09fcff 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -178,6 +178,7 @@
 	libcore/include
 
 LOCAL_SHARED_LIBRARIES := \
+	libmemtrack \
 	libandroidfw \
 	libexpat \
 	libnativehelper \
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index aa5b254..15792e8 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -20,6 +20,7 @@
 #include <utils/String8.h>
 #include "utils/misc.h"
 #include "cutils/debugger.h"
+#include <memtrack/memtrack.h>
 
 #include <cutils/log.h>
 #include <fcntl.h>
@@ -57,7 +58,9 @@
     HEAP_OAT,
     HEAP_ART,
     HEAP_UNKNOWN_MAP,
-    HEAP_GPU,
+    HEAP_GRAPHICS,
+    HEAP_GL,
+    HEAP_OTHER_MEMTRACK,
 
     HEAP_DALVIK_NORMAL,
     HEAP_DALVIK_LARGE,
@@ -66,7 +69,7 @@
     HEAP_DALVIK_CODE_CACHE,
 
     _NUM_HEAP,
-    _NUM_EXCLUSIVE_HEAP = HEAP_GPU+1,
+    _NUM_EXCLUSIVE_HEAP = HEAP_OTHER_MEMTRACK+1,
     _NUM_CORE_HEAP = HEAP_NATIVE+1
 };
 
@@ -98,6 +101,8 @@
 
 jfieldID otherStats_field;
 
+static bool memtrackLoaded;
+
 struct stats_t {
     int pss;
     int swappablePss;
@@ -139,70 +144,68 @@
 #endif
 }
 
-// XXX Qualcom-specific!
-static jlong read_gpu_mem(int pid)
+// Container used to retrieve graphics memory pss
+struct graphics_memory_pss
 {
-    char line[1024];
-    jlong uss = 0;
-    unsigned temp;
+    int graphics;
+    int gl;
+    int other;
+};
 
-    char tmp[128];
-    FILE *fp;
-
-    sprintf(tmp, "/d/kgsl/proc/%d/mem", pid);
-    fp = fopen(tmp, "r");
-    if (fp == 0) {
-        //ALOGI("Unable to open: %s", tmp);
-        return 0;
+/*
+ * Uses libmemtrack to retrieve graphics memory that the process is using.
+ * Any graphics memory reported in /proc/pid/smaps is not included here.
+ */
+static int read_memtrack_memory(struct memtrack_proc* p, int pid, struct graphics_memory_pss* graphics_mem)
+{
+    int err = memtrack_proc_get(p, pid);
+    if (err != 0) {
+        ALOGE("failed to get memory consumption info: %d", err);
+        return err;
     }
 
-    while (true) {
-        if (fgets(line, 1024, fp) == NULL) {
-            break;
-        }
+    ssize_t pss = memtrack_proc_graphics_pss(p);
+    if (pss < 0) {
+        ALOGE("failed to get graphics pss: %d", pss);
+        return pss;
+    }
+    graphics_mem->graphics = pss / 1024;
 
-        //ALOGI("Read: %s", line);
+    pss = memtrack_proc_gl_pss(p);
+    if (pss < 0) {
+        ALOGE("failed to get gl pss: %d", pss);
+        return pss;
+    }
+    graphics_mem->gl = pss / 1024;
 
-        // Format is:
-        //  gpuaddr useraddr     size    id flags       type            usage sglen
-        // 54676000 54676000     4096     1 ----p     gpumem      arraybuffer     1
-        //
-        // If useraddr is 0, this is gpu mem not otherwise accounted
-        // against the process.
+    pss = memtrack_proc_other_pss(p);
+    if (pss < 0) {
+        ALOGE("failed to get other pss: %d", pss);
+        return pss;
+    }
+    graphics_mem->other = pss / 1024;
 
-        // Make sure line is long enough.
-        int i = 0;
-        while (i < 9) {
-            if (line[i] == 0) {
-                break;
-            }
-            i++;
-        }
-        if (i < 9) {
-            //ALOGI("Early line term!");
-            continue;
-        }
+    return 0;
+}
 
-        // Look to see if useraddr is 00000000.
-        while (i < 17) {
-            if (line[i] != '0') {
-                break;
-            }
-            i++;
-        }
-        if (i < 17) {
-            //ALOGI("useraddr not 0!");
-            continue;
-        }
-
-        uss += atoi(line + i);
-        //ALOGI("Uss now: %ld", uss);
+/*
+ * Retrieves the graphics memory that is unaccounted for in /proc/pid/smaps.
+ */
+static int read_memtrack_memory(int pid, struct graphics_memory_pss* graphics_mem)
+{
+    if (!memtrackLoaded) {
+        return -1;
     }
 
-    fclose(fp);
+    struct memtrack_proc* p = memtrack_proc_new();
+    if (p == NULL) {
+        ALOGE("failed to create memtrack_proc");
+        return -1;
+    }
 
-    // Convert from bytes to KB.
-    return uss / 1024;
+    int err = read_memtrack_memory(p, pid, graphics_mem);
+    memtrack_proc_destroy(p);
+    return err;
 }
 
 static void read_mapinfo(FILE *fp, stats_t* stats)
@@ -405,12 +408,19 @@
     stats_t stats[_NUM_HEAP];
     memset(&stats, 0, sizeof(stats));
 
-
     load_maps(pid, stats);
 
-    jlong gpu = read_gpu_mem(pid);
-    stats[HEAP_GPU].pss += gpu;
-    stats[HEAP_GPU].privateDirty += gpu;
+    struct graphics_memory_pss graphics_mem;
+    if (read_memtrack_memory(pid, &graphics_mem) == 0) {
+        stats[HEAP_GRAPHICS].pss = graphics_mem.graphics;
+        stats[HEAP_GRAPHICS].privateDirty = graphics_mem.graphics;
+        stats[HEAP_GL].pss = graphics_mem.gl;
+        stats[HEAP_GL].privateDirty = graphics_mem.gl;
+        stats[HEAP_OTHER_MEMTRACK].pss = graphics_mem.other;
+        stats[HEAP_OTHER_MEMTRACK].privateDirty = graphics_mem.other;
+    } else {
+        ALOGE("Failed to read gpu memory");
+    }
 
     for (int i=_NUM_CORE_HEAP; i<_NUM_EXCLUSIVE_HEAP; i++) {
         stats[HEAP_UNKNOWN].pss += stats[i].pss;
@@ -466,7 +476,10 @@
     char tmp[128];
     FILE *fp;
 
-    pss = uss = read_gpu_mem(pid);
+    struct graphics_memory_pss graphics_mem;
+    if (read_memtrack_memory(pid, &graphics_mem) == 0) {
+        pss = uss = graphics_mem.graphics + graphics_mem.gl + graphics_mem.other;
+    }
 
     sprintf(tmp, "/proc/%d/smaps", pid);
     fp = fopen(tmp, "r");
@@ -921,6 +934,14 @@
 
 int register_android_os_Debug(JNIEnv *env)
 {
+    int err = memtrack_init();
+    if (err != 0) {
+        memtrackLoaded = false;
+        ALOGE("failed to load memtrack module: %d", err);
+    } else {
+        memtrackLoaded = true;
+    }
+
     jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
 
     // Sanity check the number of other statistics expected in Java matches here.
diff --git a/packages/PrintSpooler/res/drawable-hdpi/stat_notify_error.png b/core/res/res/drawable-hdpi/ic_print_error.png
similarity index 100%
rename from packages/PrintSpooler/res/drawable-hdpi/stat_notify_error.png
rename to core/res/res/drawable-hdpi/ic_print_error.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/stat_notify_error.png b/core/res/res/drawable-mdpi/ic_print_error.png
similarity index 100%
rename from packages/PrintSpooler/res/drawable-mdpi/stat_notify_error.png
rename to core/res/res/drawable-mdpi/ic_print_error.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_error.png b/core/res/res/drawable-xhdpi/ic_print_error.png
similarity index 100%
rename from packages/PrintSpooler/res/drawable-xhdpi/stat_notify_error.png
rename to core/res/res/drawable-xhdpi/ic_print_error.png
Binary files differ
diff --git a/core/res/res/values-mcc404-mnc17/config.xml b/core/res/res/values-mcc404-mnc17/config.xml
new file mode 100644
index 0000000..685d012
--- /dev/null
+++ b/core/res/res/values-mcc404-mnc17/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show roaming icon though same named operators. -->
+    <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
+        <item>40491</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc404-mnc85/config.xml b/core/res/res/values-mcc404-mnc85/config.xml
new file mode 100644
index 0000000..fd780ab
--- /dev/null
+++ b/core/res/res/values-mcc404-mnc85/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show roaming icon though same named operators. -->
+    <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
+        <item>40483</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc530-mnc24/config.xml b/core/res/res/values-mcc530-mnc24/config.xml
new file mode 100644
index 0000000..5598e8d
--- /dev/null
+++ b/core/res/res/values-mcc530-mnc24/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show roaming icon though same named operators. -->
+    <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
+        <item>53001</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b3cb2a1..6019e36 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1259,4 +1259,13 @@
     <!-- For some operators, PDU has garbages. To fix it, need to use valid index -->
     <integer name="config_valid_wappush_index">-1</integer>
 
+    <!-- Show roaming icon though same named operators.
+         Uses "startsWith" so you can use a leading substring like the mcc or
+         use the complete mcc+mnc string.
+         Though same mcc and same operator name, some operator want to roam.
+         user of 40485 should see the roaming icon as using 40483 network
+         though same Reliance network.
+         To do this, add 40483 item to values-mcc404-mnc85/config.xml -->
+    <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
+    </string-array>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c20c427..d0c24e2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1876,13 +1876,13 @@
       user dictionary.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
-    <string name="permlab_sdcardRead" product="nosdcard">test access to protected storage</string>
+    <string name="permlab_sdcardRead" product="nosdcard">read the contents of your USB storage</string>
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_sdcardRead" product="default">test access to protected storage</string>
+    <string name="permlab_sdcardRead" product="default">read the contents of your SD card</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
-    <string name="permdesc_sdcardRead" product="nosdcard">Allows the app to test a permission for USB storage that will be available on future devices. </string>
+    <string name="permdesc_sdcardRead" product="nosdcard">Allows the app to read the contents of your USB storage.</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_sdcardRead" product="default">Allows the app to test a permission for the SD card that will be available on future devices.</string>
+    <string name="permdesc_sdcardRead" product="default">Allows the app to read the contents of your SD card.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
     <string name="permlab_sdcardWrite" product="nosdcard">modify or delete the contents of your USB storage</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 57a4bb7..f739bed 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -975,6 +975,7 @@
   <java-symbol type="array" name="config_cdma_dun_supported_types" />
   <java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
   <java-symbol type="array" name="config_operatorConsideredNonRoaming" />
+  <java-symbol type="array" name="config_sameNamedOperatorConsideredRoaming" />
 
   <java-symbol type="drawable" name="default_wallpaper" />
   <java-symbol type="drawable" name="indicator_input_error" />
@@ -1037,6 +1038,7 @@
   <java-symbol type="drawable" name="ic_media_stop" />
   <java-symbol type="drawable" name="ic_text_dot" />
   <java-symbol type="drawable" name="ic_print" />
+  <java-symbol type="drawable" name="ic_print_error" />
   <java-symbol type="drawable" name="indicator_code_lock_drag_direction_green_up" />
   <java-symbol type="drawable" name="indicator_code_lock_drag_direction_red_up" />
   <java-symbol type="drawable" name="indicator_code_lock_point_area_default_holo" />
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index 6d9a60d..5d179a6 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -74,7 +74,7 @@
 
 <p>
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Action Bar Icons']);"
-    href="{@docRoot}downloads/design/Android_Design_Icons_20120814.zip">Action Bar Icon Pack</a>
+    href="{@docRoot}downloads/design/Android_Design_Icons_20130926.zip">Action Bar Icon Pack</a>
 </p>
 
   </div>
diff --git a/docs/html/design/patterns/actionbar.jd b/docs/html/design/patterns/actionbar.jd
index ceb5a4c..2c59149 100644
--- a/docs/html/design/patterns/actionbar.jd
+++ b/docs/html/design/patterns/actionbar.jd
@@ -182,7 +182,7 @@
 <p>
 
 <a onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Action Bar Icons (@actionbar page)']);"
-   href="{@docRoot}downloads/design/Android_Design_Icons_20120814.zip">Download the Action Bar Icon Pack</a>
+   href="{@docRoot}downloads/design/Android_Design_Icons_20130926.zip">Download the Action Bar Icon Pack</a>
 
 </p>
 
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index 0d2cdbb..0ce2faf 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -139,7 +139,7 @@
 </p>
 <p>
 <a onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Action Bar Icons (@iconography page)']);"
-   href="{@docRoot}downloads/design/Android_Design_Icons_20120814.zip">Download the Action Bar Icon Pack</a>
+   href="{@docRoot}downloads/design/Android_Design_Icons_20130926.zip">Download the Action Bar Icon Pack</a>
 </p>
 
 <div class="layout-content-row">
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index 3a416f9..9bff5d4 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -74,7 +74,7 @@
 http://developer.android.com/downloads/design/Android_Design_Illustrator_Vectors_20120814.ai
 http://developer.android.com/downloads/design/Android_Design_OmniGraffle_Stencil_20120814.graffle
 http://developer.android.com/downloads/design/Android_Design_Holo_Widgets_20120814.zip
-http://developer.android.com/downloads/design/Android_Design_Icons_20120814.zip
+http://developer.android.com/downloads/design/Android_Design_Icons_20130926.zip
 http://developer.android.com/downloads/design/Roboto_Hinted_20120823.zip
 http://developer.android.com/downloads/design/Roboto_Specimen_Book_20111129.pdf
 http://developer.android.com/downloads/design/Android_Design_Color_Swatches_20120229.zip
diff --git a/docs/html/training/implementing-navigation/nav-drawer.jd b/docs/html/training/implementing-navigation/nav-drawer.jd
index 2b5e4f8..9a94810 100644
--- a/docs/html/training/implementing-navigation/nav-drawer.jd
+++ b/docs/html/training/implementing-navigation/nav-drawer.jd
@@ -26,9 +26,9 @@
 </div>
 
 <div class="download-box">
-<a href="http://developer.android.com/downloads/design/Android_Navigation_Drawer_Icon_20130516.zip"
-  class="button">Download the nav drawer icons</a>
-<p class="filename">Android_Navigation_Drawer_Icon_20130516.zip</p>
+<a href="http://developer.android.com/downloads/design/Android_Design_Icons_20130926.zip"
+  class="button">Download the Action Bar Icon Pack</a>
+<p class="filename">Android_Design_Icons_20130926.zip</p>
 </div>
 
 </div>
@@ -304,8 +304,8 @@
   <li>The {@link android.app.Activity} hosting the drawer.
   <li>The {@link android.support.v4.widget.DrawerLayout}.
   <li>A drawable resource to use as the drawer indicator.
-   <p><a href="http://developer.android.com/downloads/design/Android_Navigation_Drawer_Icon_20130516.zip"
->Download the standard navigation icons</a> (available for both dark and light themes).</p>
+   <p>The standard navigation drawer icon is available in the <a href="http://developer.android.com/downloads/design/Android_Design_Icons_20130926.zip"
+>Download the Action Bar Icon Pack</a>.</p>
   <li>A String resource to describe the "open drawer" action (for accessibility).
   <li>A String resource to describe the "close drawer" action (for accessibility).
 </ul>
diff --git a/docs/html/training/sharing/send.jd b/docs/html/training/sharing/send.jd
index 9cb8eac..ed9e12e 100644
--- a/docs/html/training/sharing/send.jd
+++ b/docs/html/training/sharing/send.jd
@@ -134,34 +134,26 @@
   <li>You can use a MIME type of {@code "*/*"}, but this will only match activities that are able to
 handle generic data streams.</li>
   <li>The receiving application needs permission to access the data the {@link android.net.Uri}
-points to. There are a number of ways to handle this:
+points to. The recommended ways to do this are:
   <ul>
-    <li>Write the data to a file on external/shared storage (such as the SD card), which all apps
-can read. Use {@link android.net.Uri#fromFile(java.io.File) Uri.fromFile()} to create the
-{@link android.net.Uri} that can be passed to the share intent. However, keep in mind that not
-all applications process a {@code file://} style {@link android.net.Uri}.</li>
-    <li>Write the data to a file in your own application directory using {@link
-android.content.Context#openFileOutput(java.lang.String, int) openFileOutput()} with mode {@link
-android.content.Context#MODE_WORLD_READABLE} after which {@link
-android.content.Context#getFileStreamPath(java.lang.String) getFileStreamPath()} can be used to
-return a {@link java.io.File}. As with the previous option, {@link
-android.net.Uri#fromFile(java.io.File) Uri.fromFile()} will create a {@code file://} style {@link
-android.net.Uri} for your share intent.</li>
-    <li>Media files like images, videos and audio can be scanned and added to the system {@link
-android.provider.MediaStore} using {@link
+    <li>Store the data in your own {@link android.content.ContentProvider}, making sure that other
+apps have the correct permission to access your provider. The preferred mechanism for providing
+access is to use <a
+href="{@docRoot}guide/topics/security/permissions.html#uri">per-URI permissions</a> which are
+temporary and only grant access to the receiving application. An easy way to create a
+{@link android.content.ContentProvider} like this is to use the
+{@link android.support.v4.content.FileProvider} helper class.</li>
+    <li>Use the system {@link android.provider.MediaStore}. The {@link android.provider.MediaStore}
+is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API
+level 11) it can also store non-media types (see
+{@link android.provider.MediaStore.Files MediaStore.Files} for more info). Files can be inserted
+into the {@link android.provider.MediaStore} using {@link
 android.media.MediaScannerConnection#scanFile(android.content.Context, java.lang.String[],
-java.lang.String[], android.media.MediaScannerConnection.OnScanCompletedListener) scanFile()}. The
-{@link
-android.media.MediaScannerConnection.OnScanCompletedListener#onScanCompleted(java.lang.String,
-android.net.Uri) onScanCompleted()} callback returns a {@code content://} style {@link
-android.net.Uri} suitable for including in your share intent.</li>
-    <li>Images can be inserted into the system {@link android.provider.MediaStore} using {@link
-android.provider.MediaStore.Images.Media#insertImage(android.content.ContentResolver,
-android.graphics.Bitmap, java.lang.String, java.lang.String) insertImage()} which will return a
-{@code content://} style {@link android.net.Uri} suitable for including in a share intent.</li>
-    <li>Store the data in your own {@link android.content.ContentProvider}, make sure that other
-apps have the correct permission to access your provider (or use <a
-href="{@docRoot}guide/topics/security/security.html#uri">per-URI permissions</a>).</li>
+java.lang.String[], android.media.MediaScannerConnection.OnScanCompletedListener) scanFile()} after
+which a {@code content://} style {@link android.net.Uri} suitable for sharing is passed to the
+provided {@link android.media.MediaScannerConnection.OnScanCompletedListener#onScanCompleted(
+java.lang.String, android.net.Uri) onScanCompleted()} callback. Note that once added to the system
+{@link android.provider.MediaStore} the content is accessible to any app on the device.</li>
   </ul>
   </li>
 </ul>
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index c335e55..1283e9b 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -280,7 +280,7 @@
     private boolean playFallbackRingtone() {
         if (mAudioManager.getStreamVolume(mStreamType) != 0) {
             int ringtoneType = RingtoneManager.getDefaultType(mUri);
-            if (ringtoneType != -1 &&
+            if (ringtoneType == -1 ||
                     RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) != null) {
                 // Default ringtone, try fallback ringtone.
                 try {
@@ -309,6 +309,8 @@
                 } catch (NotFoundException nfe) {
                     Log.e(TAG, "Fallback ringtone does not exist");
                 }
+            } else {
+                Log.w(TAG, "not playing fallback for " + mUri);
             }
         }
         return false;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index aef61c7..13ce52e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -16,6 +16,7 @@
 
 package com.android.mediaframeworktest.integration;
 
+import android.graphics.ImageFormat;
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CameraCharacteristics;
@@ -24,6 +25,10 @@
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.utils.BinderHolder;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.RemoteException;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -43,19 +48,32 @@
     private static int NUM_CALLBACKS_CHECKED = 10;
     // Wait for capture result timeout value: 1500ms
     private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
+    // Default size is VGA, which is mandatory camera supported image size by CDD.
+    private static final int DEFAULT_IMAGE_WIDTH = 640;
+    private static final int DEFAULT_IMAGE_HEIGHT = 480;
+    private static final int MAX_NUM_IMAGES = 5;
 
     private int mCameraId;
     private ICameraDeviceUser mCameraUser;
     private CameraBinderTestUtils mUtils;
     private ICameraDeviceCallbacks.Stub mMockCb;
     private Surface mSurface;
-    // Need hold a Surfacetexture reference during a test execution, otherwise,
-    // it could be GCed during a test, which causes camera run into bad state.
-    private SurfaceTexture mSurfaceTexture;
+    private HandlerThread mHandlerThread;
+    private Handler mHandler;
+    ImageReader mImageReader;
 
     public CameraDeviceBinderTest() {
     }
 
+    private class ImageDropperListener implements ImageReader.OnImageAvailableListener {
+
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            Image image = reader.acquireNextImage();
+            if (image != null) image.close();
+        }
+    }
+
     public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
 
         @Override
@@ -75,9 +93,13 @@
      }
 
     private void createDefaultSurface() {
-        mSurfaceTexture = new SurfaceTexture(/* ignored */0);
-        mSurfaceTexture.setDefaultBufferSize(640, 480);
-        mSurface = new Surface(mSurfaceTexture);
+        mImageReader =
+                ImageReader.newInstance(DEFAULT_IMAGE_WIDTH,
+                        DEFAULT_IMAGE_HEIGHT,
+                        ImageFormat.YUV_420_888,
+                        MAX_NUM_IMAGES);
+        mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler);
+        mSurface = mImageReader.getSurface();
     }
 
     private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
@@ -134,6 +156,9 @@
                 clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
         mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
         assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
         createDefaultSurface();
 
         Log.v(TAG, String.format("Camera %s connected", mCameraId));
@@ -144,7 +169,8 @@
         mCameraUser.disconnect();
         mCameraUser = null;
         mSurface.release();
-        mSurfaceTexture.release();
+        mImageReader.close();
+        mHandlerThread.quitSafely();
     }
 
     @SmallTest
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_drawer_glyph.png b/packages/DocumentsUI/res/drawable-hdpi/ic_drawer_glyph.png
index 053c0b8..251ecfb 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_drawer_glyph.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_drawer_glyph.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_sortby_am.png b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_sortby_am.png
index 78638f73..0d4cdc1 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_menu_sortby_am.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_menu_sortby_am.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_drawer_glyph.png b/packages/DocumentsUI/res/drawable-mdpi/ic_drawer_glyph.png
index f616d3b..ae0da34 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_drawer_glyph.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_drawer_glyph.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_sortby_am.png b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_sortby_am.png
index 2155d02..2768b1c 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_menu_sortby_am.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_menu_sortby_am.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_glyph.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_glyph.png
index 002ccd9..7402c6d 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_glyph.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_glyph.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_sortby_am.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_sortby_am.png
index 85c8734..f24ca1a 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_sortby_am.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_menu_sortby_am.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_glyph.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_glyph.png
index adee4a3..4160699 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_glyph.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_glyph.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_sortby_am.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_sortby_am.png
index 867c8e8..8f19afa 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_sortby_am.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_menu_sortby_am.png
Binary files differ
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 79ab28d..138f523 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -77,7 +77,6 @@
 import com.android.documentsui.RecentsProvider.StateColumns;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Predicate;
 import com.google.android.collect.Lists;
 
 import java.util.ArrayList;
@@ -95,8 +94,6 @@
 
     private AbsListView mCurrentView;
 
-    private Predicate<DocumentInfo> mFilter;
-
     public static final int TYPE_NORMAL = 1;
     public static final int TYPE_SEARCH = 2;
     public static final int TYPE_RECENT_OPEN = 3;
@@ -354,8 +351,6 @@
     private void updateDisplayState() {
         final State state = getDisplayState(this);
 
-        mFilter = new MimePredicate(state.acceptMimes);
-
         if (mLastMode == state.derivedMode && mLastShowSize == state.showSize) return;
         mLastMode = state.derivedMode;
         mLastShowSize = state.showSize;
@@ -399,8 +394,10 @@
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
             final Cursor cursor = mAdapter.getItem(position);
             if (cursor != null) {
-                final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
-                if (mFilter.apply(doc)) {
+                final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+                final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+                if (isDocumentEnabled(docMimeType, docFlags)) {
+                    final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
                     ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
                 }
             }
@@ -479,11 +476,10 @@
                 final Cursor cursor = mAdapter.getItem(position);
                 if (cursor != null) {
                     final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
-
-                    // Only valid if non-directory matches filter
-                    final State state = getDisplayState(DirectoryFragment.this);
-                    valid = !Document.MIME_TYPE_DIR.equals(docMimeType)
-                            && MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
+                    final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+                    if (!Document.MIME_TYPE_DIR.equals(docMimeType)) {
+                        valid = isDocumentEnabled(docMimeType, docFlags);
+                    }
                 }
 
                 if (!valid) {
@@ -896,14 +892,7 @@
                 line2.setVisibility(hasLine2 ? View.VISIBLE : View.GONE);
             }
 
-            boolean enabled = Document.MIME_TYPE_DIR.equals(docMimeType)
-                    || MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
-
-            // Read-only files aren't actually enabled when creating
-            if (state.action == ACTION_CREATE && (docFlags & Document.FLAG_SUPPORTS_WRITE) == 0) {
-                enabled = false;
-            }
-
+            final boolean enabled = isDocumentEnabled(docMimeType, docFlags);
             if (enabled) {
                 setEnabledRecursive(convertView, true);
                 icon.setAlpha(1f);
@@ -1067,4 +1056,20 @@
             }
         }
     }
+
+    private boolean isDocumentEnabled(String docMimeType, int docFlags) {
+        final State state = getDisplayState(DirectoryFragment.this);
+
+        // Read-only files are disabled when creating
+        if (state.action == ACTION_CREATE && (docFlags & Document.FLAG_SUPPORTS_WRITE) == 0) {
+            return false;
+        }
+
+        // Directories are always enabled
+        if (Document.MIME_TYPE_DIR.equals(docMimeType)) {
+            return true;
+        }
+
+        return MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
index 9861399..57fc7e4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.DocumentsContract;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -209,6 +210,9 @@
         if (requestCode == CODE_READ) {
             final Uri uri = data != null ? data.getData() : null;
             if (uri != null) {
+                if (DocumentsContract.isDocumentUri(this, uri)) {
+                    result += "; DOC_ID";
+                }
                 getContentResolver()
                         .takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 InputStream is = null;
@@ -228,6 +232,9 @@
         } else if (requestCode == CODE_WRITE) {
             final Uri uri = data != null ? data.getData() : null;
             if (uri != null) {
+                if (DocumentsContract.isDocumentUri(this, uri)) {
+                    result += "; DOC_ID";
+                }
                 getContentResolver()
                         .takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                 OutputStream os = null;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 0ef5f56..ed28da5 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -16,7 +16,6 @@
 
 package com.android.externalstorage;
 
-import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.MatrixCursor;
@@ -166,11 +165,12 @@
 
         int flags = 0;
 
-        if (file.isDirectory() && file.canWrite()) {
-            flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
-        }
         if (file.canWrite()) {
-            flags |= Document.FLAG_SUPPORTS_WRITE;
+            if (file.isDirectory()) {
+                flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
+            } else {
+                flags |= Document.FLAG_SUPPORTS_WRITE;
+            }
             flags |= Document.FLAG_SUPPORTS_DELETE;
         }
 
diff --git a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
index 65d1ee72..c3c5021 100644
--- a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
@@ -45,7 +45,7 @@
         android:ellipsize="end"
         android:textIsSelectable="false"
         android:visibility="gone"
-        android:textColor="@color/item_text_color"
+        android:textColor="@color/print_option_title"
         android:duplicateParentState="true">
     </TextView>
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
index b4eb08a..3a1a3c4 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
@@ -128,7 +128,7 @@
     @Override
     protected void onStartLoading() {
         if (DEBUG) {
-            Log.i(LOG_TAG, "onStartLoading()" + FusedPrintersProvider.this.hashCode());
+            Log.i(LOG_TAG, "onStartLoading() " + FusedPrintersProvider.this.hashCode());
         }
         // The contract is that if we already have a valid,
         // result the we have to deliver it immediately.
@@ -143,7 +143,7 @@
     @Override
     protected void onStopLoading() {
         if (DEBUG) {
-            Log.i(LOG_TAG, "onStopLoading()" + FusedPrintersProvider.this.hashCode());
+            Log.i(LOG_TAG, "onStopLoading() " + FusedPrintersProvider.this.hashCode());
         }
         onCancelLoad();
     }
@@ -151,7 +151,7 @@
     @Override
     protected void onForceLoad() {
         if (DEBUG) {
-            Log.i(LOG_TAG, "onForceLoad()" + FusedPrintersProvider.this.hashCode());
+            Log.i(LOG_TAG, "onForceLoad() " + FusedPrintersProvider.this.hashCode());
         }
         loadInternal();
     }
@@ -161,37 +161,52 @@
             PrintManager printManager = (PrintManager) getContext()
                     .getSystemService(Context.PRINT_SERVICE);
             mDiscoverySession = printManager.createPrinterDiscoverySession();
-            mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() {
-                @Override
-                public void onPrintersChanged() {
-                    ArrayMap<PrinterId, PrinterInfo> printersMap =
-                            new ArrayMap<PrinterId, PrinterInfo>();
-                    List<PrinterInfo> printers = mDiscoverySession.getPrinters();
-                    final int printerCount = printers.size();
-                    for (int i = 0; i < printerCount; i++) {
-                        PrinterInfo printer = printers.get(i);
-                        printersMap.put(printer.getId(), printer);
-                    }
-                    computeAndDeliverResult(printersMap);
-                }
-            });
             mPersistenceManager.readPrinterHistory();
         }
         if (mPersistenceManager.isReadHistoryCompleted()
                 && !mDiscoverySession.isPrinterDiscoveryStarted()) {
+            mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() {
+                @Override
+                public void onPrintersChanged() {
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "onPrintersChanged() count:"
+                                + mDiscoverySession.getPrinters().size()
+                                + " " + FusedPrintersProvider.this.hashCode());
+                    }
+                    updatePrinters(mDiscoverySession.getPrinters());
+                }
+            });
             final int favoriteCount = mFavoritePrinters.size();
             List<PrinterId> printerIds = new ArrayList<PrinterId>(favoriteCount);
             for (int i = 0; i < favoriteCount; i++) {
                 printerIds.add(mFavoritePrinters.get(i).getId());
             }
             mDiscoverySession.startPrinterDisovery(printerIds);
+            List<PrinterInfo> printers = mDiscoverySession.getPrinters();
+            if (!printers.isEmpty()) {
+                updatePrinters(printers);
+            }
         }
     }
 
+    private void updatePrinters(List<PrinterInfo> printers) {
+        if (mPrinters.equals(printers)) {
+            return;
+        }
+        ArrayMap<PrinterId, PrinterInfo> printersMap =
+                new ArrayMap<PrinterId, PrinterInfo>();
+        final int printerCount = printers.size();
+        for (int i = 0; i < printerCount; i++) {
+            PrinterInfo printer = printers.get(i);
+            printersMap.put(printer.getId(), printer);
+        }
+        computeAndDeliverResult(printersMap);
+    }
+
     @Override
     protected boolean onCancelLoad() {
         if (DEBUG) {
-            Log.i(LOG_TAG, "onCancelLoad()" + FusedPrintersProvider.this.hashCode());
+            Log.i(LOG_TAG, "onCancelLoad() " + FusedPrintersProvider.this.hashCode());
         }
         return cancelInternal();
     }
@@ -214,7 +229,7 @@
     @Override
     protected void onReset() {
         if (DEBUG) {
-            Log.i(LOG_TAG, "onReset()" + FusedPrintersProvider.this.hashCode());
+            Log.i(LOG_TAG, "onReset() " + FusedPrintersProvider.this.hashCode());
         }
         onStopLoading();
         mPrinters.clear();
@@ -227,7 +242,7 @@
     @Override
     protected void onAbandon() {
         if (DEBUG) {
-            Log.i(LOG_TAG, "onAbandon()" + FusedPrintersProvider.this.hashCode());
+            Log.i(LOG_TAG, "onAbandon() " + FusedPrintersProvider.this.hashCode());
         }
         onStopLoading();
     }
@@ -288,7 +303,8 @@
 
         public void readPrinterHistory() {
             if (DEBUG) {
-                Log.i(LOG_TAG, "read history started");
+                Log.i(LOG_TAG, "read history started "
+                        + FusedPrintersProvider.this.hashCode());
             }
             mReadHistoryInProgress = true;
             mReadTask = new ReadTask();
@@ -364,7 +380,7 @@
             @Override
             protected void onPostExecute(List<PrinterInfo> printers) {
                 if (DEBUG) {
-                    Log.i(LOG_TAG, "read history completed"
+                    Log.i(LOG_TAG, "read history completed "
                             + FusedPrintersProvider.this.hashCode());
                 }
 
@@ -393,7 +409,10 @@
                 try {
                     in = mStatePersistFile.openRead();
                 } catch (FileNotFoundException fnfe) {
-                    Log.i(LOG_TAG, "No existing printer history.");
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "No existing printer history "
+                                + FusedPrintersProvider.this.hashCode());
+                    }
                     return new ArrayList<PrinterInfo>();
                 }
                 try {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
index 25bb071..dae7770 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
@@ -32,7 +32,7 @@
 import android.print.PrintJobId;
 import android.print.PrintJobInfo;
 import android.print.PrintManager;
-import android.text.TextUtils;
+import android.provider.Settings;
 import android.util.Log;
 
 /**
@@ -47,9 +47,9 @@
     private static final String INTENT_ACTION_CANCEL_PRINTJOB = "INTENT_ACTION_CANCEL_PRINTJOB";
     private static final String INTENT_ACTION_RESTART_PRINTJOB = "INTENT_ACTION_RESTART_PRINTJOB";
 
-    private static final String INTENT_EXTRA_PRINTJOB_ID = "INTENT_EXTRA_PRINTJOB_ID";
-    private static final String INTENT_EXTRA_PRINTJOB_LABEL = "INTENT_EXTRA_PRINTJOB_LABEL";
-    private static final String INTENT_EXTRA_PRINTER_NAME = "INTENT_EXTRA_PRINTER_NAME";
+    private static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
+    private static final String EXTRA_PRINTJOB_LABEL = "EXTRA_PRINTJOB_LABEL";
+    private static final String EXTRA_PRINTER_NAME = "EXTRA_PRINTER_NAME";
 
     private final Context mContext;
     private final NotificationManager mNotificationManager;
@@ -89,6 +89,7 @@
 
     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()))
@@ -102,18 +103,16 @@
     }
 
     private void createFailedNotification(PrintJobInfo printJob) {
-        String reason = !TextUtils.isEmpty(printJob.getStateReason())
-                ? printJob.getStateReason() : mContext.getString(R.string.reason_unknown);
-
         Notification.Builder builder = new Notification.Builder(mContext)
-                .setSmallIcon(R.drawable.stat_notify_error)
+                .setContentIntent(createContentIntent(printJob.getId()))
+                .setSmallIcon(com.android.internal.R.drawable.ic_print_error)
                 .setContentTitle(mContext.getString(R.string.failed_notification_title_template,
                         printJob.getLabel()))
                 .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
                         createCancelIntent(printJob))
                 .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.restart),
                         createRestartIntent(printJob.getId()))
-                .setContentText(reason)
+                .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
                 .setShowWhen(true);
@@ -121,16 +120,14 @@
     }
 
     private void createBlockedNotification(PrintJobInfo printJob) {
-        String reason = !TextUtils.isEmpty(printJob.getStateReason())
-                ? printJob.getStateReason() : mContext.getString(R.string.reason_unknown);
-
         Notification.Builder builder = new Notification.Builder(mContext)
-                .setSmallIcon(R.drawable.stat_notify_error)
+                .setContentIntent(createContentIntent(printJob.getId()))
+                .setSmallIcon(com.android.internal.R.drawable.ic_print_error)
                 .setContentTitle(mContext.getString(R.string.blocked_notification_title_template,
                         printJob.getLabel()))
                 .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
                         createCancelIntent(printJob))
-                .setContentText(reason)
+                .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
                 .setShowWhen(true);
@@ -141,19 +138,25 @@
         mNotificationManager.cancel(printJobId.flattenToString(), 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);
+    }
+
     private PendingIntent createCancelIntent(PrintJobInfo printJob) {
         Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class);
         intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + printJob.getId().flattenToString());
-        intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJob.getId());
-        intent.putExtra(INTENT_EXTRA_PRINTJOB_LABEL, printJob.getLabel());
-        intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterName());
+        intent.putExtra(EXTRA_PRINT_JOB_ID, printJob.getId());
+        intent.putExtra(EXTRA_PRINTJOB_LABEL, printJob.getLabel());
+        intent.putExtra(EXTRA_PRINTER_NAME, printJob.getPrinterName());
         return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
     }
 
     private PendingIntent createRestartIntent(PrintJobId printJobId) {
         Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class);
         intent.setAction(INTENT_ACTION_RESTART_PRINTJOB + "_" + printJobId.flattenToString());
-        intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJobId);
+        intent.putExtra(EXTRA_PRINT_JOB_ID, printJobId);
         return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
     }
 
@@ -164,12 +167,12 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (action != null && action.startsWith(INTENT_ACTION_CANCEL_PRINTJOB)) {
-                PrintJobId printJobId = intent.getExtras().getParcelable(INTENT_EXTRA_PRINTJOB_ID);
-                String printJobLabel = intent.getExtras().getString(INTENT_EXTRA_PRINTJOB_LABEL);
-                String printerName = intent.getExtras().getString(INTENT_EXTRA_PRINTER_NAME);
+                PrintJobId printJobId = intent.getExtras().getParcelable(EXTRA_PRINT_JOB_ID);
+                String printJobLabel = intent.getExtras().getString(EXTRA_PRINTJOB_LABEL);
+                String printerName = intent.getExtras().getString(EXTRA_PRINTER_NAME);
                 handleCancelPrintJob(context, printJobId, printJobLabel, printerName);
             } else if (action != null && action.startsWith(INTENT_ACTION_RESTART_PRINTJOB)) {
-                PrintJobId printJobId = intent.getExtras().getParcelable(INTENT_EXTRA_PRINTJOB_ID);
+                PrintJobId printJobId = intent.getExtras().getParcelable(EXTRA_PRINT_JOB_ID);
                 handleRestartPrintJob(context, printJobId);
             }
         }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 05b0b69..8d11a93 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -56,6 +56,7 @@
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.text.TextWatcher;
+import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -77,6 +78,8 @@
 import android.widget.Spinner;
 import android.widget.TextView;
 
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -88,12 +91,11 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import libcore.io.IoUtils;
-
 /**
  * Activity for configuring a print job.
  */
@@ -144,7 +146,28 @@
             "(?=[]\\[+&|!(){}^\"~*?:\\\\])");
 
     private static final Pattern PATTERN_PAGE_RANGE = Pattern.compile(
-            "([0-9]+[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*[,]?[\\s]*)+");
+            "[\\s]*[0-9]*[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*?(([,])"
+            + "[\\s]*[0-9]*[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*|[\\s]*)+");
+
+    // The list of countries where Letter is the default paper size. Culled from
+    // the OpenOffice wiki at http://wiki.openoffice.org/wiki/DefaultPaperSize.
+    private static final Set<String> sLetterDefaultCountries = new ArraySet<String>();
+    static {
+        sLetterDefaultCountries.add("US");
+        sLetterDefaultCountries.add("CA");
+        sLetterDefaultCountries.add("BZ");
+        sLetterDefaultCountries.add("CL");
+        sLetterDefaultCountries.add("CR");
+        sLetterDefaultCountries.add("GT");
+        sLetterDefaultCountries.add("NI");
+        sLetterDefaultCountries.add("PA");
+        sLetterDefaultCountries.add("PR");
+        sLetterDefaultCountries.add("SV");
+        sLetterDefaultCountries.add("VE");
+        sLetterDefaultCountries.add("MX");
+        sLetterDefaultCountries.add("CO");
+        sLetterDefaultCountries.add("PH");
+    }
 
     public static final PageRange[] ALL_PAGES_ARRAY = new PageRange[] {PageRange.ALL_PAGES};
 
@@ -1076,9 +1099,13 @@
                     return;
                 }
 
+                // The range
                 Matcher matcher = PATTERN_DIGITS.matcher(text);
                 while (matcher.find()) {
-                    String numericString = text.substring(matcher.start(), matcher.end());
+                    String numericString = text.substring(matcher.start(), matcher.end()).trim();
+                    if (TextUtils.isEmpty(numericString)) {
+                        continue;
+                    }
                     final int pageIndex = Integer.parseInt(numericString);
                     if (pageIndex < 1 || pageIndex > mDocument.info.getPageCount()) {
                         mPageRangeEditText.setError("");
@@ -1087,7 +1114,9 @@
                     }
                 }
 
-                //TODO: Catch the error if start is less grater than the end.
+                // We intentionally do not catch the case of the from page being
+                // greater than the to page. When computing the requested pages
+                // we just swap them if necessary.
 
                 mPageRangeEditText.setError(null);
                 mPrintButton.setEnabled(true);
@@ -1506,18 +1535,21 @@
 
                 while (mStringCommaSplitter.hasNext()) {
                     String range = mStringCommaSplitter.next().trim();
+                    if (TextUtils.isEmpty(range)) {
+                        continue;
+                    }
                     final int dashIndex = range.indexOf('-');
                     final int fromIndex;
                     final int toIndex;
 
                     if (dashIndex > 0) {
-                        fromIndex = Integer.parseInt(range.substring(0, dashIndex)) - 1;
+                        fromIndex = Integer.parseInt(range.substring(0, dashIndex).trim()) - 1;
                         // It is possible that the dash is at the end since the input
                         // verification can has to allow the user to keep entering if
                         // this would lead to a valid input. So we handle this.
                         toIndex = (dashIndex < range.length() - 1)
                                 ? Integer.parseInt(range.substring(dashIndex + 1,
-                                        range.length())) - 1 : fromIndex;
+                                        range.length()).trim()) - 1 : fromIndex;
                     } else {
                         fromIndex = toIndex = Integer.parseInt(range) - 1;
                     }
@@ -1817,8 +1849,7 @@
 
                 // Range options
                 PrintDocumentInfo info = mDocument.info;
-                if (info != null && (info.getPageCount() > 0
-                        || info.getPageCount() == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) {
+                if (info != null && info.getPageCount() > 0) {
                     if (info.getPageCount() == 1) {
                         mRangeOptionsSpinner.setEnabled(false);
                     } else {
@@ -2127,12 +2158,20 @@
             }
 
             private PrinterInfo createFakePdfPrinter() {
+                final MediaSize defaultMediaSize;
+                String currentCountry = getResources().getConfiguration().locale.getCountry();
+                if (sLetterDefaultCountries.contains(currentCountry)) {
+                    defaultMediaSize = MediaSize.NA_LETTER;
+                } else {
+                    defaultMediaSize = MediaSize.ISO_A4;
+                }
+
                 PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
 
                 PrinterCapabilitiesInfo capabilities =
                         new PrinterCapabilitiesInfo.Builder(printerId)
-                    .addMediaSize(MediaSize.ISO_A4, true)
-                    .addMediaSize(MediaSize.NA_LETTER, false)
+                    .addMediaSize(MediaSize.ISO_A4, MediaSize.ISO_A4 == defaultMediaSize)
+                    .addMediaSize(MediaSize.NA_LETTER, MediaSize.NA_LETTER == defaultMediaSize)
                     .addResolution(new Resolution("PDF resolution", "PDF resolution",
                             300, 300), true)
                     .setColorModes(PrintAttributes.COLOR_MODE_COLOR
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index ce1f6ec..62b35fe 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -155,23 +155,33 @@
             @SuppressWarnings("deprecation")
             @Override
             public void createPrintJob(PrintJobInfo printJob, IPrintClient client,
-                    IPrintDocumentAdapter printAdapter) throws RemoteException {
-                    PrintSpoolerService.this.createPrintJob(printJob);
+                IPrintDocumentAdapter printAdapter) throws RemoteException {
+                PrintSpoolerService.this.createPrintJob(printJob);
 
-                    Intent intent = new Intent(printJob.getId().flattenToString());
-                    intent.setClass(PrintSpoolerService.this, PrintJobConfigActivity.class);
-                    intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
-                            printAdapter.asBinder());
-                    intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_JOB, printJob);
+                Intent intent = new Intent(printJob.getId().flattenToString());
+                intent.setClass(PrintSpoolerService.this, PrintJobConfigActivity.class);
+                intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
+                        printAdapter.asBinder());
+                intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_JOB, printJob);
 
-                    IntentSender sender = PendingIntent.getActivity(
-                            PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
-                            | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
+                IntentSender sender = PendingIntent.getActivity(
+                        PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
+                        | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
 
-                    Message message = mHandlerCaller.obtainMessageOO(
-                            HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
-                            client, sender);
-                    mHandlerCaller.executeOrSendMessage(message);
+                Message message = mHandlerCaller.obtainMessageIIO(
+                        HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
+                        printJob.getAppId(), 0, printJob.getId());
+                mHandlerCaller.executeOrSendMessage(message);
+
+                message = mHandlerCaller.obtainMessageOO(
+                        HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
+                        client, sender);
+                mHandlerCaller.executeOrSendMessage(message);
+
+                printJob.setCreationTime(System.currentTimeMillis());
+                synchronized (mLock) {
+                    mPersistanceManager.writeStateLocked();
+                }
             }
 
             @Override
@@ -240,12 +250,13 @@
     }
 
     private final class HandlerCallerCallback implements HandlerCaller.Callback {
-        public static final int MSG_SET_CLIENT = 9;
-        public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 10;
-        public static final int MSG_ON_PRINT_JOB_QUEUED = 11;
-        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 12;
-        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 13;
-        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 14;
+        public static final int MSG_SET_CLIENT = 1;
+        public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2;
+        public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
+        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 4;
+        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 5;
+        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 6;
+        public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 7;
 
         @Override
         public void executeMessage(Message message) {
@@ -310,6 +321,18 @@
                 case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
                     checkAllPrintJobsHandled();
                 } break;
+
+                case MSG_ON_PRINT_JOB_STATE_CHANGED: {
+                    if (mClient != null) {
+                        PrintJobId printJobId = (PrintJobId) message.obj;
+                        final int appId = message.arg1;
+                        try {
+                            mClient.onPrintJobStateChanged(printJobId, appId);
+                        } catch (RemoteException re) {
+                            Slog.e(LOG_TAG, "Error notify for print job state change.", re);
+                        }
+                    }
+                } break;
             }
         }
     }
@@ -511,6 +534,11 @@
         synchronized (mLock) {
             PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
             if (printJob != null) {
+                final int oldState = printJob.getState();
+                if (oldState == state) {
+                    return false;
+                }
+
                 success = true;
 
                 printJob.setState(state);
@@ -553,6 +581,11 @@
                 if (!hasActivePrintJobsLocked()) {
                     notifyOnAllPrintJobsHandled();
                 }
+
+                Message message = mHandlerCaller.obtainMessageIIO(
+                        HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
+                        printJob.getAppId(), 0, printJob.getId());
+                mHandlerCaller.executeOrSendMessage(message);
             }
         }
 
@@ -706,7 +739,10 @@
         private static final String ATTR_APP_ID = "appId";
         private static final String ATTR_USER_ID = "userId";
         private static final String ATTR_TAG = "tag";
+        private static final String ATTR_CREATION_TIME = "creationTime";
         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 TAG_MEDIA_SIZE = "mediaSize";
         private static final String TAG_RESOLUTION = "resolution";
@@ -714,7 +750,7 @@
 
         private static final String ATTR_COLOR_MODE = "colorMode";
 
-        private static final String ATTR_LOCAL_ID = "printerName";
+        private static final String ATTR_LOCAL_ID = "localId";
         private static final String ATTR_SERVICE_NAME = "serviceName";
 
         private static final String ATTR_WIDTH_MILS = "widthMils";
@@ -794,7 +830,17 @@
                     if (tag != null) {
                         serializer.attribute(null, ATTR_TAG, tag);
                     }
+                    serializer.attribute(null, ATTR_CREATION_TIME, String.valueOf(
+                            printJob.getCreationTime()));
                     serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies()));
+                    String printerName = printJob.getPrinterName();
+                    if (!TextUtils.isEmpty(printerName)) {
+                        serializer.attribute(null, ATTR_PRINTER_NAME, printerName);
+                    }
+                    String stateReason = printJob.getStateReason();
+                    if (!TextUtils.isEmpty(stateReason)) {
+                        serializer.attribute(null, ATTR_STATE_REASON, stateReason);
+                    }
 
                     PrinterId printerId = printJob.getPrinterId();
                     if (printerId != null) {
@@ -979,8 +1025,14 @@
             printJob.setUserId(userId);
             String tag = parser.getAttributeValue(null, ATTR_TAG);
             printJob.setTag(tag);
+            String creationTime = parser.getAttributeValue(null, ATTR_CREATION_TIME);
+            printJob.setCreationTime(Long.parseLong(creationTime));
             String copies = parser.getAttributeValue(null, ATTR_COPIES);
             printJob.setCopies(Integer.parseInt(copies));
+            String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME);
+            printJob.setPrinterName(printerName);
+            String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON);
+            printJob.setStateReason(stateReason);
 
             parser.next();
 
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
index fd9d9db..ece947a 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_location_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_location_on.png
index 0df2411..b03d30c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_location_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_location_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
index 59edd98..fe33891 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
index 450dd70..edd03e3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
index ae6fee5..5d90d2b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
index 67fa3ad..9e18046 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
index ba367ea..a2f2cf7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
index 3ce0c6e..bd5d922 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
index d502d5d..9a02199 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
index 2f44643..aa1b25c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png
index d37e446..7db72fb 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0.png
new file mode 100644
index 0000000..295d8fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0_fully.png
new file mode 100644
index 0000000..d875faf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1.png
new file mode 100644
index 0000000..f3235e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1_fully.png
new file mode 100644
index 0000000..6cd4809
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2.png
new file mode 100644
index 0000000..9bbf17e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2_fully.png
new file mode 100644
index 0000000..c301366
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3.png
new file mode 100644
index 0000000..56244b9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..d2af46d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..cee9234
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_idle.png
new file mode 100644
index 0000000..91768a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_idle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png
index d5e1da4..5ba15a7 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0.png
new file mode 100644
index 0000000..383015e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0_fully.png
new file mode 100644
index 0000000..ab73c9f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1.png
new file mode 100644
index 0000000..07a81a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1_fully.png
new file mode 100644
index 0000000..9303aee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2.png
new file mode 100644
index 0000000..def4430
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2_fully.png
new file mode 100644
index 0000000..43c9fb2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3.png
new file mode 100644
index 0000000..ddbd04a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..c8493ff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..de04176
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_idle.png
new file mode 100644
index 0000000..abee91e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_idle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png
index 8d53a7c..294ae48 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0.png
new file mode 100644
index 0000000..e00a33a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0_fully.png
new file mode 100644
index 0000000..21286bf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1.png
new file mode 100644
index 0000000..8be5950
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1_fully.png
new file mode 100644
index 0000000..7cdd393
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2.png
new file mode 100644
index 0000000..07aa536
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2_fully.png
new file mode 100644
index 0000000..3ca6529
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3.png
new file mode 100644
index 0000000..095a1a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..eb8e313
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..0f571e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_idle.png
new file mode 100644
index 0000000..3edbd14
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_idle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png
index 255b39d..7b7e329 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0.png
new file mode 100644
index 0000000..4cb1410
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0_fully.png
new file mode 100644
index 0000000..7a0b11c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1.png
new file mode 100644
index 0000000..12d5d6f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1_fully.png
new file mode 100644
index 0000000..08da7e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2.png
new file mode 100644
index 0000000..6ecd2e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2_fully.png
new file mode 100644
index 0000000..9e7e3f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3.png
new file mode 100644
index 0000000..bdd4f59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..1eb0547
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..06e4480
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_idle.png
new file mode 100644
index 0000000..f904325
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_idle.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
index 31fbf40..8ab2e1e 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_location_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_location_on.png
index c6f41d2..867c57d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_location_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_location_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
index 62ab39a..0c63793 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
index 4082a2c..c16c289 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
index 8c1c15a..f4f59b4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
index 6ba3496..1d2c557 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
index 4a91d65..ebf7888 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
index 18d6198..b100728 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
index a11e57e..8b8e872 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
index 5a3a627..de78a9c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
index ea4b8d6..32e6c49 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_location_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_location_on.png
index 77c3ec0..6300bdc 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_location_on.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_location_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
index 4378a895..8a0a50f 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
index dc144aa..58ff765 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
index 722148c..ca14841 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
index a3d11f2..9b1a47c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
index 9e63b78..dd00668 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
index 74f9129..556c710 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
index 38838fe..b87eb87 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
index 28d26f2..fe7c1af 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png
index 9867b0b..3d3c9bb 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_location_on.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_location_on.png
index 3175636..d6d4c70 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_location_on.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_location_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png
index 3356733..1da84be 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png
index 080bdda..17989b5 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png
index 0d1e47a..8733bc3 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png
index f565046..54cc847 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png
index 378d433..5d5ba2f 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png
index 3bd5759..6a5035e 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png
index 3d56db4..82a891f 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png
index 2d24d99..399bb97 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml b/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
index cabfaa5..6bf31e0 100644
--- a/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
+++ b/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
@@ -66,5 +66,6 @@
         android:text="@string/quick_settings_rssi_label"
         android:layout_centerHorizontal="true"
         android:layout_below="@id/rssi_images"
+        android:textAllCaps="@bool/quick_settings_rssi_tile_capitalization"
         />
 </RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index b3c2f6e..d7312df 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -95,12 +95,12 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     />
-                <!-- battery must be padded below by 1px to match assets -->
+                <!-- battery must be padded below by 2px to match assets -->
                 <com.android.systemui.BatteryMeterView
                     android:id="@+id/battery"
                     android:layout_height="16dp"
-                    android:layout_width="10dp"
-                    android:paddingBottom="1px"
+                    android:layout_width="10.5dp"
+                    android:layout_marginBottom="2px"
                     android:layout_marginStart="4dip"
                     />
             </LinearLayout>
diff --git a/packages/SystemUI/res/values-mcc262-mnc07/config.xml b/packages/SystemUI/res/values-mcc262-mnc07/config.xml
new file mode 100644
index 0000000..7b7b8f3
--- /dev/null
+++ b/packages/SystemUI/res/values-mcc262-mnc07/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <!-- Whether or not the RSSI tile is capitalized or not. -->
+    <bool name="quick_settings_rssi_tile_capitalization">false</bool>
+</resources>
+
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index b2c8aee..bfb600d 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -52,13 +52,12 @@
         <item>#FFFFFFFF</item>
     </array>
     <array name="batterymeter_bolt_points">
-        <item>88</item> <item>0</item>
-        <item>459</item><item>1</item>
-        <item>238</item><item>333</item>
-        <item>525</item><item>310</item>
-        <item>120</item><item>840</item>
-        <item>82</item> <item>818</item>
-        <item>246</item><item>373</item>
-        <item>0</item>  <item>408</item>
+        <item>73</item> <item>0</item>
+        <item>392</item><item>0</item>
+        <item>201</item><item>259</item>
+        <item>442</item><item>259</item>
+        <item>4</item>  <item>703</item>
+        <item>157</item><item>334</item>
+        <item>0</item>  <item>334</item>
     </array>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 757121f..2f0d0f9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -35,5 +35,6 @@
     <color name="notification_panel_scrim_color">#B0000000</color>
     <color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
     <color name="batterymeter_charge_color">#FFFFFFFF</color>
+    <color name="batterymeter_bolt_color">#B2000000</color><!-- 70% black -->
     <color name="status_bar_clock_color">#FFFFFFFF</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8ce959f..3869db3 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -87,6 +87,9 @@
     <!-- Whether rotation lock shows up in quick settings or not -->
     <bool name="quick_settings_show_rotation_lock">false</bool>
 
+    <!-- Whether or not the RSSI tile is capitalized or not. -->
+    <bool name="quick_settings_rssi_tile_capitalization">true</bool>
+
     <!-- Timeouts for brightness dialog to disappear -->
     <integer name="quick_settings_brightness_dialog_short_timeout">2000</integer>
     <integer name="quick_settings_brightness_dialog_long_timeout">4000</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 2be8ee5..150f132 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -47,6 +47,8 @@
     public static final int FULL = 96;
     public static final int EMPTY = 4;
 
+    public static final float SUBPIXEL = 0.4f;  // inset rects for softer edges
+
     int[] mColors;
 
     boolean mShowPercent = true;
@@ -186,8 +188,15 @@
 
         mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mFramePaint.setColor(res.getColor(R.color.batterymeter_frame_color));
+        mFramePaint.setDither(true);
+        mFramePaint.setStrokeWidth(0);
+        mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
+        mFramePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
+
         mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mBatteryPaint.setColor(0xFF00FF00); // will be replaced by something from mColors
+        mBatteryPaint.setDither(true);
+        mBatteryPaint.setStrokeWidth(0);
+        mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
 
         mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mTextPaint.setColor(0xFFFFFFFF);
@@ -205,9 +214,9 @@
 
         mBoltPaint = new Paint();
         mBoltPaint.setAntiAlias(true);
-        mBoltPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));  // punch hole
-        setLayerType(LAYER_TYPE_HARDWARE, null);
+        mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color));
         mBoltPoints = loadBoltPoints(res);
+        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
     }
 
     private static float[] loadBoltPoints(Resources res) {
@@ -264,16 +273,23 @@
                 mFrame.left + width * 0.25f,
                 mFrame.top,
                 mFrame.right - width * 0.25f,
-                mFrame.top + mButtonHeight);
+                mFrame.top + mButtonHeight + 5 /*cover frame border of intersecting area*/);
+
+        mButtonFrame.top += SUBPIXEL;
+        mButtonFrame.left += SUBPIXEL;
+        mButtonFrame.right -= SUBPIXEL;
 
         mFrame.top += mButtonHeight;
+        mFrame.left += SUBPIXEL;
+        mFrame.top += SUBPIXEL;
+        mFrame.right -= SUBPIXEL;
+        mFrame.bottom -= SUBPIXEL;
 
         // first, draw the battery shape
         c.drawRect(mFrame, mFramePaint);
 
         // fill 'er up
-        final int pct = tracker.level;
-        final int color = tracker.plugged ? mChargeColor : getColorForLevel(pct);
+        final int color = tracker.plugged ? mChargeColor : getColorForLevel(level);
         mBatteryPaint.setColor(color);
 
         if (level >= FULL) {
@@ -294,10 +310,10 @@
 
         if (tracker.plugged) {
             // draw the bolt
-            final int bl = (int)(mFrame.left + width / 4f);
-            final int bt = (int)(mFrame.top + height / 6f);
-            final int br = (int)(mFrame.right - width / 5f);
-            final int bb = (int)(mFrame.bottom - height / 6f);
+            final int bl = (int)(mFrame.left + mFrame.width() / 4.5f);
+            final int bt = (int)(mFrame.top + mFrame.height() / 6f);
+            final int br = (int)(mFrame.right - mFrame.width() / 7f);
+            final int bb = (int)(mFrame.bottom - mFrame.height() / 10f);
             if (mBoltFrame.left != bl || mBoltFrame.top != bt
                     || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
                 mBoltFrame.set(bl, bt, br, bb);
@@ -325,7 +341,7 @@
                             : (tracker.level == 100 ? 0.38f : 0.5f)));
             mTextHeight = -mTextPaint.getFontMetrics().ascent;
 
-            final String str = String.valueOf(SINGLE_DIGIT_PERCENT ? (pct/10) : pct);
+            final String str = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level);
             final float x = mWidth * 0.5f;
             final float y = (mHeight + mTextHeight) * 0.47f;
             c.drawText(str,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3c11933..babe0e6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -41,6 +41,7 @@
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
+import com.android.internal.util.Preconditions;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
@@ -6062,12 +6063,8 @@
             }
 
             // Persistable only supported through Intents
-            modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-            if (modeFlags == 0) {
-                throw new IllegalArgumentException("Mode flags must be "
-                        + "FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION");
-            }
+            Preconditions.checkFlagsArgument(modeFlags,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
             grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags,
                     null);
@@ -6408,11 +6405,8 @@
     public void takePersistableUriPermission(Uri uri, int modeFlags) {
         enforceNotIsolatedCaller("takePersistableUriPermission");
 
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if (modeFlags == 0) {
-            return;
-        }
+        Preconditions.checkFlagsArgument(modeFlags,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
         synchronized (this) {
             final int callingUid = Binder.getCallingUid();
@@ -6436,11 +6430,8 @@
     public void releasePersistableUriPermission(Uri uri, int modeFlags) {
         enforceNotIsolatedCaller("releasePersistableUriPermission");
 
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if (modeFlags == 0) {
-            return;
-        }
+        Preconditions.checkFlagsArgument(modeFlags,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
         synchronized (this) {
             final int callingUid = Binder.getCallingUid();
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index 7057c24..5868c08 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -22,6 +22,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.util.Preconditions;
 import com.google.android.collect.Sets;
 
 import java.io.PrintWriter;
@@ -131,10 +132,7 @@
      * @return if mode changes should trigger persisting.
      */
     boolean takePersistableModes(int modeFlags) {
-        if ((~persistableModeFlags & modeFlags) != 0) {
-            Slog.w(TAG, "Trying to take 0x" + Integer.toHexString(modeFlags) + " but only 0x"
-                    + Integer.toHexString(persistableModeFlags) + " are available");
-        }
+        Preconditions.checkFlagsArgument(modeFlags, persistableModeFlags);
 
         final int before = persistedModeFlags;
         persistedModeFlags |= (persistableModeFlags & modeFlags);
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index d0e9fe1..c33134a 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -110,6 +110,7 @@
     private static final String USER_PHOTO_FILENAME = "photo.png";
 
     private static final String RESTRICTIONS_FILE_PREFIX = "res_";
+    private static final String XML_SUFFIX = ".xml";
 
     private static final int MIN_USER_ID = 10;
 
@@ -622,7 +623,7 @@
      */
     private void writeUserLocked(UserInfo userInfo) {
         FileOutputStream fos = null;
-        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + ".xml"));
+        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + XML_SUFFIX));
         try {
             fos = userFile.startWrite();
             final BufferedOutputStream bos = new BufferedOutputStream(fos);
@@ -751,7 +752,7 @@
         FileInputStream fis = null;
         try {
             AtomicFile userFile =
-                    new AtomicFile(new File(mUsersDir, Integer.toString(id) + ".xml"));
+                    new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
             fis = userFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
@@ -909,7 +910,7 @@
                         if (all) {
                             resFile.delete();
                         } else {
-                            String pkg = fileName.substring(RESTRICTIONS_FILE_PREFIX.length());
+                            String pkg = restrictionsFileNameToPackage(fileName);
                             if (!isPackageInstalled(pkg, userId)) {
                                 resFile.delete();
                             }
@@ -926,7 +927,7 @@
     private void cleanAppRestrictionsForPackage(String pkg, int userId) {
         synchronized (mPackagesLock) {
             File dir = Environment.getUserSystemDirectory(userId);
-            File resFile = new File(dir, RESTRICTIONS_FILE_PREFIX + pkg);
+            File resFile = new File(dir, packageToRestrictionsFileName(pkg));
             if (resFile.exists()) {
                 resFile.delete();
             }
@@ -1072,7 +1073,7 @@
 
         mRestrictionsPinStates.remove(userHandle);
         // Remove user file
-        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
+        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
         userFile.delete();
         // Update the user list
         writeUserListLocked();
@@ -1307,7 +1308,7 @@
         try {
             AtomicFile restrictionsFile =
                     new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
-                            RESTRICTIONS_FILE_PREFIX + packageName + ".xml"));
+                            packageToRestrictionsFileName(packageName)));
             fis = restrictionsFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
@@ -1368,7 +1369,7 @@
         FileOutputStream fos = null;
         AtomicFile restrictionsFile = new AtomicFile(
                 new File(Environment.getUserSystemDirectory(userId),
-                        RESTRICTIONS_FILE_PREFIX + packageName + ".xml"));
+                        packageToRestrictionsFileName(packageName)));
         try {
             fos = restrictionsFile.startWrite();
             final BufferedOutputStream bos = new BufferedOutputStream(fos);
@@ -1498,6 +1499,15 @@
         }
     }
 
+    private String packageToRestrictionsFileName(String packageName) {
+        return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
+    }
+
+    private String restrictionsFileNameToPackage(String fileName) {
+        return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(),
+                (int) (fileName.length() - XML_SUFFIX.length()));
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 9810bf0..d4583b5 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -32,9 +32,11 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.print.IPrintClient;
 import android.print.IPrintDocumentAdapter;
+import android.print.IPrintJobStateChangeListener;
 import android.print.IPrintManager;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.PrintAttributes;
@@ -300,6 +302,39 @@
     }
 
     @Override
+    public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
+            int appId, int userId) throws RemoteException {
+        final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+        final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
+        final UserState userState;
+        synchronized (mLock) {
+            userState = getOrCreateUserStateLocked(resolvedUserId);
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            userState.addPrintJobStateChangeListener(listener, resolvedAppId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener,
+            int userId) {
+        final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+        final UserState userState;
+        synchronized (mLock) {
+            userState = getOrCreateUserStateLocked(resolvedUserId);
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            userState.removePrintJobStateChangeListener(listener);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index 1bde6d7..f98a805 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -91,6 +91,7 @@
     public static interface PrintSpoolerCallbacks {
         public void onPrintJobQueued(PrintJobInfo printJob);
         public void onAllPrintJobsForServiceHandled(ComponentName printService);
+        public void onPrintJobStateChanged(PrintJobId printJobId, int appId);
     }
 
     public RemotePrintSpooler(Context context, int userId,
@@ -345,6 +346,10 @@
         }
     }
 
+    private void onPrintJobStateChanged(PrintJobId printJobId, int appId) {
+        mCallbacks.onPrintJobStateChanged(printJobId, appId);
+    }
+
     private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
         synchronized (mLock) {
             if (mRemoteInstance != null) {
@@ -618,5 +623,18 @@
                 }
             }
         }
+
+        @Override
+        public void onPrintJobStateChanged(PrintJobId printJobId, int appId) {
+            RemotePrintSpooler spooler = mWeakSpooler.get();
+            if (spooler != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    spooler.onPrintJobStateChanged(printJobId, appId);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
     }
 }
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index 8c21827..e5f5842 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -36,6 +36,7 @@
 import android.os.UserManager;
 import android.print.IPrintClient;
 import android.print.IPrintDocumentAdapter;
+import android.print.IPrintJobStateChangeListener;
 import android.print.IPrinterDiscoveryObserver;
 import android.print.PrintAttributes;
 import android.print.PrintJobId;
@@ -103,8 +104,12 @@
 
     private final RemotePrintSpooler mSpooler;
 
+    private final Handler mHandler;
+
     private PrinterDiscoverySessionMediator mPrinterDiscoverySession;
 
+    private List<PrintJobStateChangeListenerRecord> mPrintJobStateChangeListenerRecords;
+
     private boolean mDestroyed;
 
     public UserState(Context context, int userId, Object lock) {
@@ -112,6 +117,7 @@
         mUserId = userId;
         mLock = lock;
         mSpooler = new RemotePrintSpooler(context, userId, this);
+        mHandler = new UserStateHandler(context.getMainLooper());
         synchronized (mLock) {
             enableSystemPrintServicesOnFirstBootLocked();
         }
@@ -164,6 +170,7 @@
         printJob.setLabel(printJobName);
         printJob.setAttributes(attributes);
         printJob.setState(PrintJobInfo.STATE_CREATED);
+        printJob.setCopies(1);
 
         // Spin the spooler to add the job and show the config UI.
         new AsyncTask<Void, Void, Void>() {
@@ -351,6 +358,51 @@
         }
     }
 
+    public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
+            int appId) throws RemoteException {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mPrintJobStateChangeListenerRecords == null) {
+                mPrintJobStateChangeListenerRecords =
+                        new ArrayList<PrintJobStateChangeListenerRecord>();
+            }
+            mPrintJobStateChangeListenerRecords.add(
+                    new PrintJobStateChangeListenerRecord(listener, appId) {
+                @Override
+                public void onBinderDied() {
+                    mPrintJobStateChangeListenerRecords.remove(this);
+                }
+            });
+        }
+    }
+
+    public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener) {
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mPrintJobStateChangeListenerRecords == null) {
+                return;
+            }
+            final int recordCount = mPrintJobStateChangeListenerRecords.size();
+            for (int i = 0; i < recordCount; i++) {
+                PrintJobStateChangeListenerRecord record =
+                        mPrintJobStateChangeListenerRecords.get(i);
+                if (record.listener.asBinder().equals(listener.asBinder())) {
+                    mPrintJobStateChangeListenerRecords.remove(i);
+                    break;
+                }
+            }
+            if (mPrintJobStateChangeListenerRecords.isEmpty()) {
+                mPrintJobStateChangeListenerRecords = null;
+            }
+        }
+    }
+
+    @Override
+    public void onPrintJobStateChanged(PrintJobId printJobId, int appId) {
+        mHandler.obtainMessage(UserStateHandler.MSG_DISPATCH_PRINT_JOB_STATE_CHANGED,
+                appId, 0, printJobId).sendToTarget();
+    }
+
     @Override
     public void onPrintersAdded(List<PrinterInfo> printers) {
         synchronized (mLock) {
@@ -698,6 +750,65 @@
         }
     }
 
+    private void handleDispatchPrintJobStateChanged(PrintJobId printJobId, int appId) {
+        final List<PrintJobStateChangeListenerRecord> records;
+        synchronized (mLock) {
+            if (mPrintJobStateChangeListenerRecords == null) {
+                return;
+            }
+            records = new ArrayList<PrintJobStateChangeListenerRecord>(
+                    mPrintJobStateChangeListenerRecords);
+        }
+        final int recordCount = records.size();
+        for (int i = 0; i < recordCount; i++) {
+            PrintJobStateChangeListenerRecord record = records.get(i);
+            if (record.appId == PrintManager.APP_ID_ANY
+                    || record.appId == appId)
+            try {
+                record.listener.onPrintJobStateChanged(printJobId);
+            } catch (RemoteException re) {
+                Log.e(LOG_TAG, "Error notifying for print job state change", re);
+            }
+        }
+    }
+
+    private final class UserStateHandler extends Handler {
+        public static final int MSG_DISPATCH_PRINT_JOB_STATE_CHANGED = 1;
+
+        public UserStateHandler(Looper looper) {
+            super(looper, null, false);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            if (message.what == MSG_DISPATCH_PRINT_JOB_STATE_CHANGED) {
+                PrintJobId printJobId = (PrintJobId) message.obj;
+                final int appId = message.arg1;
+                handleDispatchPrintJobStateChanged(printJobId, appId);
+            }
+        }
+    }
+
+    private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient {
+        final IPrintJobStateChangeListener listener;
+        final int appId;
+
+        public PrintJobStateChangeListenerRecord(IPrintJobStateChangeListener listener,
+                int appId) throws RemoteException {
+            this.listener = listener;
+            this.appId = appId;
+            listener.asBinder().linkToDeath(this, 0);
+        }
+
+        @Override
+        public void binderDied() {
+            listener.asBinder().unlinkToDeath(this, 0);
+            onBinderDied();
+        }
+
+        public abstract void onBinderDied();
+    }
+
     private class PrinterDiscoverySessionMediator {
         private final ArrayMap<PrinterId, PrinterInfo> mPrinters =
                 new ArrayMap<PrinterId, PrinterInfo>();