Merge "Ratings for RemoteControl" into klp-dev
diff --git a/Android.mk b/Android.mk
index 8e59ffa..998e65d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -162,8 +162,6 @@
 	core/java/android/os/IVibratorService.aidl \
 	core/java/android/service/notification/INotificationListener.aidl \
 	core/java/android/print/ILayoutResultCallback.aidl \
-	core/java/android/print/IPrinterDiscoverySessionController.aidl \
-	core/java/android/print/IPrinterDiscoverySessionObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
 	core/java/android/print/IPrintClient.aidl \
 	core/java/android/print/IPrintManager.aidl \
@@ -264,7 +262,7 @@
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
 	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
-	packages/services/Proxy/com/android/net/IProxyService.aidl \
+	packages/services/PacProcessor/com/android/net/IProxyService.aidl \
 
 # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
 LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
@@ -723,13 +721,13 @@
 
 LOCAL_DROIDDOC_OPTIONS:=\
 		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-                $(web_docs_sample_code_flags) \
-                -offlinemode \
+		-offlinemode \
 		-title "Android SDK" \
 		-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
 		-todo $(OUT_DOCS)/$(LOCAL_MODULE)-docs-todo.html \
 		-sdkvalues $(OUT_DOCS) \
 		-hdf android.whichdoc offline
+#		$(web_docs_sample_code_flags)
 
 
 LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
@@ -765,7 +763,7 @@
 		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
 		-toroot / \
 		-hdf android.whichdoc online 
-#       $(web_docs_sample_code_flags)
+#		$(web_docs_sample_code_flags)
 
 LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
 
@@ -789,11 +787,11 @@
 
 LOCAL_DROIDDOC_OPTIONS:= \
 		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-		$(web_docs_sample_code_flags) \
 		-devsite \
 		-toroot / \
 		-hdf android.whichdoc online \
 		-hdf devsite true
+#		$(web_docs_sample_code_flags)
 
 LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
 
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8fd5186..0d5590d 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -170,6 +170,10 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoveryObserver.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/printservice/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/packages/services/Proxy/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoverySessionObserver.*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoverySessionClient.*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/os/IBattery*)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index b252864..f341597 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5014,7 +5014,8 @@
   }
 
   public final class BluetoothGatt implements android.bluetooth.BluetoothProfile {
-    method public void abortReliableWrite(android.bluetooth.BluetoothDevice);
+    method public void abortReliableWrite();
+    method public deprecated void abortReliableWrite(android.bluetooth.BluetoothDevice);
     method public boolean beginReliableWrite();
     method public void close();
     method public boolean connect();
@@ -8830,6 +8831,7 @@
     method public void setHeight(int);
     method public void setPixel(int, int, int);
     method public void setPixels(int[], int, int, int, int, int, int);
+    method public final void setPremultiplied(boolean);
     method public void setWidth(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -8879,6 +8881,7 @@
     field public boolean inMutable;
     field public boolean inPreferQualityOverSpeed;
     field public android.graphics.Bitmap.Config inPreferredConfig;
+    field public boolean inPremultiplied;
     field public boolean inPurgeable;
     field public int inSampleSize;
     field public boolean inScaled;
@@ -11014,6 +11017,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FRAME_DURATION;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEMPERATURE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TIMESTAMP;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_IDS;
@@ -11813,6 +11817,7 @@
     ctor public SettingInjectorService(java.lang.String);
     method protected abstract android.location.SettingInjectorService.Status getStatus();
     method protected final void onHandleIntent(android.content.Intent);
+    field public static final java.lang.String UPDATE_INTENT = "com.android.location.InjectedSettingChanged";
   }
 
   public static final class SettingInjectorService.Status {
@@ -12796,6 +12801,7 @@
 
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public android.media.MediaFormat getFormat();
     method public java.lang.String getLanguage();
     method public int getTrackType();
     method public void writeToParcel(android.os.Parcel, int);
@@ -12857,6 +12863,7 @@
     field public static final int CAMCORDER = 5; // 0x5
     field public static final int DEFAULT = 0; // 0x0
     field public static final int MIC = 1; // 0x1
+    field public static final int REMOTE_SUBMIX = 8; // 0x8
     field public static final int VOICE_CALL = 4; // 0x4
     field public static final int VOICE_COMMUNICATION = 7; // 0x7
     field public static final int VOICE_DOWNLINK = 3; // 0x3
@@ -15115,9 +15122,11 @@
 
   public abstract class HostApduService extends android.app.Service {
     ctor public HostApduService();
+    method public final void notifyUnhandled();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract void onDeactivated(int);
-    method public abstract byte[] processCommandApdu(byte[], int);
+    method public byte[] processCommandApdu(byte[], android.os.Bundle);
+    method public abstract deprecated byte[] processCommandApdu(byte[], int);
     method public final void sendResponseApdu(byte[]);
     field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
     field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
@@ -18616,6 +18625,7 @@
     method protected android.view.View onCreateView(android.view.ViewGroup);
     method public void onDependencyChanged(android.preference.Preference, boolean);
     method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
+    method public void onParentChanged(android.preference.Preference, boolean);
     method protected void onPrepareForRemoval();
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -19033,7 +19043,7 @@
     method public android.print.PrintAttributes getAttributes();
     method public int getCopies();
     method public int getId();
-    method public java.lang.CharSequence getLabel();
+    method public java.lang.String getLabel();
     method public android.print.PageRange[] getPages();
     method public android.print.PrinterId getPrinterId();
     method public int getState();
@@ -19157,7 +19167,7 @@
   public final class PrintJob {
     method public boolean cancel();
     method public boolean complete();
-    method public boolean fail(java.lang.CharSequence);
+    method public boolean fail(java.lang.String);
     method public android.printservice.PrintDocument getDocument();
     method public int getId();
     method public android.print.PrintJobInfo getInfo();
@@ -19186,11 +19196,15 @@
   }
 
   public abstract class PrinterDiscoverySession {
-    ctor public PrinterDiscoverySession(android.content.Context);
+    ctor public PrinterDiscoverySession();
     method public final void addPrinters(java.util.List<android.print.PrinterInfo>);
-    method public abstract void onClose();
-    method public abstract void onOpen(java.util.List<android.print.PrinterId>);
+    method public final java.util.List<android.print.PrinterInfo> getPrinters();
+    method public final boolean isDestroyed();
+    method public final boolean isPrinterDiscoveryStarted();
+    method public abstract void onDestroy();
     method public abstract void onRequestPrinterUpdate(android.print.PrinterId);
+    method public abstract void onStartPrinterDiscovery(java.util.List<android.print.PrinterId>);
+    method public abstract void onStopPrinterDiscovery();
     method public final void removePrinters(java.util.List<android.print.PrinterId>);
     method public final void updatePrinters(java.util.List<android.print.PrinterInfo>);
   }
@@ -19202,10 +19216,17 @@
   public final class AlarmClock {
     ctor public AlarmClock();
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
+    field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
+    field public static final java.lang.String EXTRA_DAYS = "android.intent.extra.alarm.DAYS";
+    field public static final java.lang.String EXTRA_DELETE_AFTER_USE = "android.intent.extra.alarm.DELETE_AFTER_USE";
     field public static final java.lang.String EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
+    field public static final java.lang.String EXTRA_LENGTH = "android.intent.extra.alarm.LENGTH";
     field public static final java.lang.String EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
     field public static final java.lang.String EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
+    field public static final java.lang.String EXTRA_RINGTONE = "android.intent.extra.alarm.RINGTONE";
     field public static final java.lang.String EXTRA_SKIP_UI = "android.intent.extra.alarm.SKIP_UI";
+    field public static final java.lang.String EXTRA_VIBRATE = "android.intent.extra.alarm.VIBRATE";
+    field public static final java.lang.String VALUE_RINGTONE_SILENT = "silent";
   }
 
   public abstract interface BaseColumns {
@@ -21136,16 +21157,20 @@
     method public static float getFloat(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static int getInt(android.content.ContentResolver, java.lang.String, int);
     method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
+    method public static final int getLocationMode(android.content.ContentResolver);
+    method public static final int getLocationModeForUser(android.content.ContentResolver, int);
     method public static long getLong(android.content.ContentResolver, java.lang.String, long);
     method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
     method public static android.net.Uri getUriFor(java.lang.String);
-    method public static final boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
+    method public static final deprecated boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
     method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
     method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
     method public static boolean putLong(android.content.ContentResolver, java.lang.String, long);
     method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String);
-    method public static final void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
+    method public static final void setLocationMode(android.content.ContentResolver, int);
+    method public static final void setLocationModeForUser(android.content.ContentResolver, int, int);
+    method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
     field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
     field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
     field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
@@ -21164,6 +21189,10 @@
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
     field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
     field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
+    field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
+    field public static final int LOCATION_MODE_OFF = 0; // 0x0
+    field public static final int LOCATION_MODE_SENSORS_ONLY = 1; // 0x1
     field public static final java.lang.String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
     field public static final java.lang.String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
     field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8f2f9ca..e02410a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -747,6 +747,7 @@
     int mResultCode = RESULT_CANCELED;
     Intent mResultData = null;
     private TranslucentConversionListener mTranslucentCallback;
+    private boolean mChangeCanvasToTranslucent;
 
     private boolean mTitleReady = false;
 
@@ -4903,7 +4904,9 @@
     public void convertFromTranslucent() {
         try {
             mTranslucentCallback = null;
-            ActivityManagerNative.getDefault().convertFromTranslucent(mToken);
+            if (ActivityManagerNative.getDefault().convertFromTranslucent(mToken)) {
+                WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, true);
+            }
         } catch (RemoteException e) {
             // pass
         }
@@ -4931,7 +4934,8 @@
     public void convertToTranslucent(TranslucentConversionListener callback) {
         try {
             mTranslucentCallback = callback;
-            ActivityManagerNative.getDefault().convertToTranslucent(mToken);
+            mChangeCanvasToTranslucent =
+                    ActivityManagerNative.getDefault().convertToTranslucent(mToken);
         } catch (RemoteException e) {
             // pass
         }
@@ -4943,6 +4947,9 @@
             mTranslucentCallback.onTranslucentConversionComplete(drawComplete);
             mTranslucentCallback = null;
         }
+        if (mChangeCanvasToTranslucent) {
+            WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false);
+        }
     }
 
     /**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c65f17e..6ac2e80 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -438,7 +438,7 @@
 
     /** @hide */
     public static boolean isLowRamDeviceStatic() {
-        return Resources.getSystem().getBoolean(com.android.internal.R.bool.config_lowRamDevice);
+        return "true".equals(SystemProperties.get("ro.config.low_ram", "false"));
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6a29552..6d72114 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1502,16 +1502,18 @@
         case CONVERT_FROM_TRANSLUCENT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            convertFromTranslucent(token);
+            boolean converted = convertFromTranslucent(token);
             reply.writeNoException();
+            reply.writeInt(converted ? 1 : 0);
             return true;
         }
 
         case CONVERT_TO_TRANSLUCENT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            convertToTranslucent(token);
+            boolean converted = convertToTranslucent(token);
             reply.writeNoException();
+            reply.writeInt(converted ? 1 : 0);
             return true;
         }
 
@@ -3876,7 +3878,7 @@
         reply.recycle();
     }
 
-    public void convertFromTranslucent(IBinder token)
+    public boolean convertFromTranslucent(IBinder token)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -3884,11 +3886,13 @@
         data.writeStrongBinder(token);
         mRemote.transact(CONVERT_FROM_TRANSLUCENT_TRANSACTION, data, reply, 0);
         reply.readException();
+        boolean res = reply.readInt() != 0;
         data.recycle();
         reply.recycle();
+        return res;
     }
 
-    public void convertToTranslucent(IBinder token)
+    public boolean convertToTranslucent(IBinder token)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -3896,8 +3900,10 @@
         data.writeStrongBinder(token);
         mRemote.transact(CONVERT_TO_TRANSLUCENT_TRANSACTION, data, reply, 0);
         reply.readException();
+        boolean res = reply.readInt() != 0;
         data.recycle();
         reply.recycle();
+        return res;
     }
 
     public void setImmersive(IBinder token, boolean immersive)
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 6d1b6fc..af9a245 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -301,8 +301,8 @@
 
     public void finishHeavyWeightApp() throws RemoteException;
 
-    public void convertFromTranslucent(IBinder token) throws RemoteException;
-    public void convertToTranslucent(IBinder token) throws RemoteException;
+    public boolean convertFromTranslucent(IBinder token) throws RemoteException;
+    public boolean convertToTranslucent(IBinder token) throws RemoteException;
     public void notifyActivityDrawn(IBinder token) throws RemoteException;
 
     public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 1acac85..7bcf43e 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -66,8 +66,9 @@
     public static final int WINDOW_STATUS_BAR = 1;
     public static final int WINDOW_NAVIGATION_BAR = 2;
 
+    public static final int WINDOW_STATE_SHOWING = 0;
     public static final int WINDOW_STATE_HIDING = 1;
-    public static final int WINDOW_STATE_SHOWING = 2;
+    public static final int WINDOW_STATE_HIDDEN = 2;
 
     private Context mContext;
     private IStatusBarService mService;
@@ -185,4 +186,12 @@
             throw new RuntimeException(ex);
         }
     }
+
+    /** @hide */
+    public static String windowStateToString(int state) {
+        if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
+        if (state == WINDOW_STATE_HIDDEN) return "WINDOW_STATE_HIDDEN";
+        if (state == WINDOW_STATE_SHOWING) return "WINDOW_STATE_SHOWING";
+        return "WINDOW_STATE_UNKNOWN";
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index be831d7..e0b1c00 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -32,10 +32,17 @@
 import android.os.UserHandle;
 import android.util.Log;
 
+import com.android.org.conscrypt.TrustedCertificateStore;
+
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Proxy;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Public interface for managing policies enforced on a device.  Most clients
@@ -1328,6 +1335,70 @@
     }
 
     /**
+     * Installs the given certificate as a User CA.
+     *
+     * @return false if the certBuffer cannot be parsed or installation is
+     *         interrupted, otherwise true
+     * @hide
+     */
+    public boolean installCaCert(byte[] certBuffer) {
+        if (mService != null) {
+            try {
+                return mService.installCaCert(certBuffer);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Uninstalls the given certificate from the list of User CAs, if present.
+     *
+     * @hide
+     */
+    public void uninstallCaCert(byte[] certBuffer) {
+        if (mService != null) {
+            try {
+                mService.uninstallCaCert(certBuffer);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Returns whether there are any user-installed CA certificates.
+     *
+     * @hide
+     */
+    public boolean hasAnyCaCertsInstalled() {
+        TrustedCertificateStore certStore = new TrustedCertificateStore();
+        Set<String> aliases = certStore.userAliases();
+        return aliases != null && !aliases.isEmpty();
+    }
+
+    /**
+     * Returns whether this certificate has been installed as a User CA.
+     *
+     * @hide
+     */
+    public boolean hasCaCertInstalled(byte[] certBuffer) {
+        TrustedCertificateStore certStore = new TrustedCertificateStore();
+        String alias;
+        byte[] pemCert;
+        try {
+            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(
+                            new ByteArrayInputStream(certBuffer));
+            return certStore.getCertificateAlias(cert) != null;
+        } catch (CertificateException ce) {
+            Log.w(TAG, "Could not parse certificate", ce);
+        }
+        return false;
+    }
+
+    /**
      * Called by an application that is administering the device to disable all cameras
      * on the device.  After setting this, no applications will be able to access any cameras
      * on the device.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9659a91..172c47c2 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -102,4 +102,7 @@
     boolean isDeviceOwner(String packageName);
     String getDeviceOwner();
     String getDeviceOwnerName();
+
+    boolean installCaCert(in byte[] certBuffer);
+    void uninstallCaCert(in byte[] certBuffer);
 }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index a8c310b..b390aa1 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -1102,7 +1102,7 @@
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
      */
-    public void abortReliableWrite(BluetoothDevice mDevice) {
+    public void abortReliableWrite() {
         if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
         if (mService == null || mClientIf == 0) return;
 
@@ -1114,6 +1114,13 @@
     }
 
     /**
+     * @deprecated Use {@link #abortReliableWrite()}
+     */
+    public void abortReliableWrite(BluetoothDevice mDevice) {
+        abortReliableWrite();
+    }
+
+    /**
      * Enable or disable notifications/indications for a given characteristic.
      *
      * <p>Once notifications are enabled for a characteristic, a
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 0aedecb..a9b7176 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.net.BaseNetworkStateTracker;
 import android.os.IBinder;
 import android.os.ServiceManager;
 import android.os.INetworkManagementService;
@@ -54,7 +55,7 @@
  *
  * @hide
  */
-public class BluetoothTetheringDataTracker implements NetworkStateTracker {
+public class BluetoothTetheringDataTracker extends BaseNetworkStateTracker {
     private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
     private static final String TAG = "BluetoothTethering";
     private static final boolean DBG = true;
@@ -66,18 +67,12 @@
     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
 
     private final Object mLinkPropertiesLock = new Object();
-    private LinkProperties mLinkProperties;
-
-    private LinkCapabilities mLinkCapabilities;
-
     private final Object mNetworkInfoLock = new Object();
-    private NetworkInfo mNetworkInfo;
 
     private BluetoothPan mBluetoothPan;
     private static String mRevTetheredIface;
     /* For sending events to connectivity service handler */
     private Handler mCsHandler;
-    protected Context mContext;
     private static BluetoothTetheringDataTracker sInstance;
     private BtdtHandler mBtdtHandler;
     private AtomicReference<AsyncChannel> mAsyncChannel = new AtomicReference<AsyncChannel>(null);
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 10ca9be..70d777f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -29,8 +29,6 @@
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 
 /**
diff --git a/core/java/android/hardware/camera2/CameraProperties.java b/core/java/android/hardware/camera2/CameraProperties.java
index e713d217..ebbdd88 100644
--- a/core/java/android/hardware/camera2/CameraProperties.java
+++ b/core/java/android/hardware/camera2/CameraProperties.java
@@ -16,10 +16,6 @@
 
 package android.hardware.camera2;
 
-import android.graphics.Rect;
-
-import java.util.List;
-
 /**
  * <p>The properties describing a
  * {@link CameraDevice CameraDevice}.</p>
@@ -384,8 +380,8 @@
      * Needed for FOV calculation for old API
      * </p>
      */
-    public static final Key<android.hardware.camera2.Size> SENSOR_INFO_PHYSICAL_SIZE =
-            new Key<android.hardware.camera2.Size>("android.sensor.info.physicalSize", android.hardware.camera2.Size.class);
+    public static final Key<float[]> SENSOR_INFO_PHYSICAL_SIZE =
+            new Key<float[]>("android.sensor.info.physicalSize", float[].class);
 
     /**
      * <p>
diff --git a/core/java/android/hardware/camera2/CameraPropertiesKeys.java b/core/java/android/hardware/camera2/CameraPropertiesKeys.java
deleted file mode 100644
index 41b31ff..0000000
--- a/core/java/android/hardware/camera2/CameraPropertiesKeys.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.camera2;
-
-import static android.hardware.camera2.CameraMetadata.Key;
-
-/**
- * ! Do not edit this file directly !
- *
- * Generated automatically from CameraPropertiesKeys.mako
- *
- * TODO: Include a hash of the input files here that the build can check.
- */
-
-/**
- * The base class for camera controls and information.
- *
- * This class defines the basic key/value map used for querying for camera
- * characteristics or capture results, and for setting camera request
- * parameters.
- *
- * @see CameraProperties
- * @see CameraMetadata
- * @hide
- **/
-public final class CameraPropertiesKeys {
-    public static final class Control {
-        public static final Key<byte[]> AE_AVAILABLE_ANTIBANDING_MODES =
-                new Key<byte[]>("android.control.aeAvailableAntibandingModes", byte[].class);
-        public static final Key<int[]> AE_AVAILABLE_TARGET_FPS_RANGES =
-                new Key<int[]>("android.control.aeAvailableTargetFpsRanges", int[].class);
-        public static final Key<int[]> AE_COMPENSATION_RANGE =
-                new Key<int[]>("android.control.aeCompensationRange", int[].class);
-        public static final Key<Rational> AE_COMPENSATION_STEP =
-                new Key<Rational>("android.control.aeCompensationStep", Rational.class);
-        public static final Key<byte[]> AF_AVAILABLE_MODES =
-                new Key<byte[]>("android.control.afAvailableModes", byte[].class);
-        public static final Key<byte[]> AVAILABLE_EFFECTS =
-                new Key<byte[]>("android.control.availableEffects", byte[].class);
-        public static final Key<byte[]> AVAILABLE_SCENE_MODES =
-                new Key<byte[]>("android.control.availableSceneModes", byte[].class);
-        public static final Key<byte[]> AVAILABLE_VIDEO_STABILIZATION_MODES =
-                new Key<byte[]>("android.control.availableVideoStabilizationModes", byte[].class);
-        public static final Key<byte[]> AWB_AVAILABLE_MODES =
-                new Key<byte[]>("android.control.awbAvailableModes", byte[].class);
-        public static final Key<Integer> MAX_REGIONS =
-                new Key<Integer>("android.control.maxRegions", int.class);
-
-    }
-
-    public static final class Flash {
-        public static final class Info {
-            public static final Key<Byte> AVAILABLE =
-                    new Key<Byte>("android.flash.info.available", byte.class);
-        }
-
-    }
-
-    public static final class Jpeg {
-        public static final Key<android.hardware.camera2.Size[]> AVAILABLE_THUMBNAIL_SIZES =
-                new Key<android.hardware.camera2.Size[]>("android.jpeg.availableThumbnailSizes", android.hardware.camera2.Size[].class);
-
-    }
-
-    public static final class Lens {
-        public static final class Info {
-            public static final Key<float[]> AVAILABLE_APERTURES =
-                    new Key<float[]>("android.lens.info.availableApertures", float[].class);
-            public static final Key<float[]> AVAILABLE_FILTER_DENSITIES =
-                    new Key<float[]>("android.lens.info.availableFilterDensities", float[].class);
-            public static final Key<float[]> AVAILABLE_FOCAL_LENGTHS =
-                    new Key<float[]>("android.lens.info.availableFocalLengths", float[].class);
-            public static final Key<byte[]> AVAILABLE_OPTICAL_STABILIZATION =
-                    new Key<byte[]>("android.lens.info.availableOpticalStabilization", byte[].class);
-            public static final Key<Float> HYPERFOCAL_DISTANCE =
-                    new Key<Float>("android.lens.info.hyperfocalDistance", float.class);
-            public static final Key<Float> MINIMUM_FOCUS_DISTANCE =
-                    new Key<Float>("android.lens.info.minimumFocusDistance", float.class);
-            public static final Key<android.hardware.camera2.Size> SHADING_MAP_SIZE =
-                    new Key<android.hardware.camera2.Size>("android.lens.info.shadingMapSize", android.hardware.camera2.Size.class);
-        }
-
-            public static final class FacingKey extends Key<Lens.FacingKey.Enum> {
-                public enum Enum {
-                    FRONT,
-                    BACK;
-                }
-
-                public static final Enum FRONT = Enum.FRONT;
-                public static final Enum BACK = Enum.BACK;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private FacingKey(String name) {
-                    super(name, Lens.FacingKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Lens.FacingKey.Enum> FACING =
-                new FacingKey("android.lens.facing");
-
-    }
-
-    public static final class Request {
-        public static final Key<int[]> MAX_NUM_OUTPUT_STREAMS =
-                new Key<int[]>("android.request.maxNumOutputStreams", int[].class);
-
-    }
-
-    public static final class Scaler {
-
-            public static final class AvailableFormatsKey extends Key<Scaler.AvailableFormatsKey.Enum[]> {
-                public enum Enum {
-                    RAW_SENSOR,
-                    YV12,
-                    YCrCb_420_SP,
-                    IMPLEMENTATION_DEFINED,
-                    YCbCr_420_888,
-                    BLOB;
-                }
-
-                public static final Enum RAW_SENSOR = Enum.RAW_SENSOR;
-                public static final Enum YV12 = Enum.YV12;
-                public static final Enum YCrCb_420_SP = Enum.YCrCb_420_SP;
-                public static final Enum IMPLEMENTATION_DEFINED = Enum.IMPLEMENTATION_DEFINED;
-                public static final Enum YCbCr_420_888 = Enum.YCbCr_420_888;
-                public static final Enum BLOB = Enum.BLOB;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AvailableFormatsKey(String name) {
-                    super(name, Scaler.AvailableFormatsKey.Enum[].class);
-                }
-
-                static {
-                    CameraMetadata.registerEnumValues(Scaler.AvailableFormatsKey.Enum.class, new int[] {
-                        0x20,  // RAW_SENSOR
-                        0x32315659,  // YV12
-                        0x11,  // YCrCb_420_SP
-                        0x22,  // IMPLEMENTATION_DEFINED
-                        0x23,  // YCbCr_420_888
-                        0x21  // BLOB
-                    });
-                }
-            }
-
-        public static final Key<Scaler.AvailableFormatsKey.Enum[]> AVAILABLE_FORMATS =
-                new AvailableFormatsKey("android.scaler.availableFormats");
-        public static final Key<long[]> AVAILABLE_JPEG_MIN_DURATIONS =
-                new Key<long[]>("android.scaler.availableJpegMinDurations", long[].class);
-        public static final Key<android.hardware.camera2.Size[]> AVAILABLE_JPEG_SIZES =
-                new Key<android.hardware.camera2.Size[]>("android.scaler.availableJpegSizes", android.hardware.camera2.Size[].class);
-        public static final Key<Float> AVAILABLE_MAX_DIGITAL_ZOOM =
-                new Key<Float>("android.scaler.availableMaxDigitalZoom", float.class);
-        public static final Key<long[]> AVAILABLE_PROCESSED_MIN_DURATIONS =
-                new Key<long[]>("android.scaler.availableProcessedMinDurations", long[].class);
-        public static final Key<android.hardware.camera2.Size[]> AVAILABLE_PROCESSED_SIZES =
-                new Key<android.hardware.camera2.Size[]>("android.scaler.availableProcessedSizes", android.hardware.camera2.Size[].class);
-
-    }
-
-    public static final class Sensor {
-        public static final class Info {
-            public static final Key<android.graphics.Rect> ACTIVE_ARRAY_SIZE =
-                    new Key<android.graphics.Rect>("android.sensor.info.activeArraySize", android.graphics.Rect.class);
-            public static final Key<int[]> SENSITIVITY_RANGE =
-                    new Key<int[]>("android.sensor.info.sensitivityRange", int[].class);
-            public static final Key<long[]> EXPOSURE_TIME_RANGE =
-                    new Key<long[]>("android.sensor.info.exposureTimeRange", long[].class);
-            public static final Key<Long> MAX_FRAME_DURATION =
-                    new Key<Long>("android.sensor.info.maxFrameDuration", long.class);
-            public static final Key<android.hardware.camera2.Size> PHYSICAL_SIZE =
-                    new Key<android.hardware.camera2.Size>("android.sensor.info.physicalSize", android.hardware.camera2.Size.class);
-        }
-        public static final Key<Rational> BASE_GAIN_FACTOR =
-                new Key<Rational>("android.sensor.baseGainFactor", Rational.class);
-        public static final Key<Integer> MAX_ANALOG_SENSITIVITY =
-                new Key<Integer>("android.sensor.maxAnalogSensitivity", int.class);
-        public static final Key<Integer> ORIENTATION =
-                new Key<Integer>("android.sensor.orientation", int.class);
-
-    }
-
-    public static final class Statistics {
-        public static final class Info {
-            public static final Key<byte[]> AVAILABLE_FACE_DETECT_MODES =
-                    new Key<byte[]>("android.statistics.info.availableFaceDetectModes", byte[].class);
-            public static final Key<Integer> MAX_FACE_COUNT =
-                    new Key<Integer>("android.statistics.info.maxFaceCount", int.class);
-        }
-
-    }
-
-    public static final class Tonemap {
-        public static final Key<Integer> MAX_CURVE_POINTS =
-                new Key<Integer>("android.tonemap.maxCurvePoints", int.class);
-
-    }
-
-    /**
-     * @hide
-     */
-    public static final class Led {
-
-            /**
-             * @hide
-             */
-            public static final class AvailableLedsKey extends Key<Led.AvailableLedsKey.Enum[]> {
-                public enum Enum {
-                    TRANSMIT;
-                }
-
-                public static final Enum TRANSMIT = Enum.TRANSMIT;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AvailableLedsKey(String name) {
-                    super(name, Led.AvailableLedsKey.Enum[].class);
-                }
-
-            }
-
-        /**
-         * @hide
-         */
-        public static final Key<Led.AvailableLedsKey.Enum[]> AVAILABLE_LEDS =
-                new AvailableLedsKey("android.led.availableLeds");
-
-    }
-
-    public static final class Info {
-
-            public static final class SupportedHardwareLevelKey extends Key<Info.SupportedHardwareLevelKey.Enum> {
-                public enum Enum {
-                    LIMITED,
-                    FULL;
-                }
-
-                public static final Enum LIMITED = Enum.LIMITED;
-                public static final Enum FULL = Enum.FULL;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private SupportedHardwareLevelKey(String name) {
-                    super(name, Info.SupportedHardwareLevelKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Info.SupportedHardwareLevelKey.Enum> SUPPORTED_HARDWARE_LEVEL =
-                new SupportedHardwareLevelKey("android.info.supportedHardwareLevel");
-
-    }
-
-}
-
-
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 28225e6..8b5bf4a 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -181,6 +181,10 @@
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
 
     /**
+     * <p>
+     * When android.sensor.awbMode is not OFF, TRANSFORM_MATRIX
+     * should be ignored.
+     * </p>
      * @see #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX
      * @see #COLOR_CORRECTION_MODE_FAST
      * @see #COLOR_CORRECTION_MODE_HIGH_QUALITY
@@ -197,7 +201,8 @@
      * This matrix is either set by HAL when the request
      * android.colorCorrection.mode is not TRANSFORM_MATRIX, or
      * directly by the application in the request when the
-     * androird.colorCorrection.mode is TRANSFORM_MATRIX.
+     * android.colorCorrection.mode is TRANSFORM_MATRIX.
+     * </p><p>
      * In the latter case, the HAL may round the matrix to account
      * for precision issues; the final rounded matrix should be
      * reported back in this matrix result metadata.
@@ -220,6 +225,11 @@
      * it should use the G_even value,and write G_odd equal to
      * G_even in the output result metadata.
      * </p><p>
+     * This array is either set by HAL when the request
+     * android.colorCorrection.mode is not TRANSFORM_MATRIX, or
+     * directly by the application in the request when the
+     * android.colorCorrection.mode is TRANSFORM_MATRIX.
+     * </p><p>
      * The ouput should be the gains actually applied by the HAL to
      * the current frame.
      * </p>
@@ -781,7 +791,10 @@
     /**
      * <p>
      * Duration each pixel is exposed to
-     * light
+     * light.
+     * </p><p>
+     * If the sensor can't expose this exact duration, it should shorten the
+     * duration exposed to the nearest possible value (rather than expose longer).
      * </p>
      * <p>
      * 1/10000 - 30 sec range. No bulb mode
@@ -808,6 +821,9 @@
      * Gain applied to image data. Must be
      * implemented through analog gain only if set to values
      * below 'maximum analog sensitivity'.
+     * </p><p>
+     * If the sensor can't apply this exact gain, it should lessen the
+     * gain to the nearest possible value (rather than gain more).
      * </p>
      * <p>
      * ISO 12232:2006 REI method
@@ -839,18 +855,30 @@
      * Table mapping blue input values to output
      * values
      * </p>
+     * <p>
+     * Tonemapping / contrast / gamma curve for the blue
+     * channel, to use when android.tonemap.mode is CONTRAST_CURVE.
+     * </p><p>
+     * See android.tonemap.curveRed for more details.
+     * </p>
      */
-    public static final Key<Float> TONEMAP_CURVE_BLUE =
-            new Key<Float>("android.tonemap.curveBlue", float.class);
+    public static final Key<float[]> TONEMAP_CURVE_BLUE =
+            new Key<float[]>("android.tonemap.curveBlue", float[].class);
 
     /**
      * <p>
      * Table mapping green input values to output
      * values
      * </p>
+     * <p>
+     * Tonemapping / contrast / gamma curve for the green
+     * channel, to use when android.tonemap.mode is CONTRAST_CURVE.
+     * </p><p>
+     * See android.tonemap.curveRed for more details.
+     * </p>
      */
-    public static final Key<Float> TONEMAP_CURVE_GREEN =
-            new Key<Float>("android.tonemap.curveGreen", float.class);
+    public static final Key<float[]> TONEMAP_CURVE_GREEN =
+            new Key<float[]>("android.tonemap.curveGreen", float[].class);
 
     /**
      * <p>
@@ -858,9 +886,17 @@
      * values
      * </p>
      * <p>
-     * .The input range must be monotonically increasing
-     * with N, and values between entries should be linearly
-     * interpolated. For example, if the array is: [0.0, 0.0,
+     * Tonemapping / contrast / gamma curve for the red
+     * channel, to use when android.tonemap.mode is CONTRAST_CURVE.
+     * </p><p>
+     * Since the input and output ranges may vary depending on
+     * the camera pipeline, the input and output pixel values
+     * are represented by normalized floating-point values
+     * between 0 and 1, with 0 == black and 1 == white.
+     * </p><p>
+     * The curve should be linearly interpolated between the
+     * defined points. The points will be listed in increasing
+     * order of P_IN. For example, if the array is: [0.0, 0.0,
      * 0.3, 0.5, 1.0, 1.0], then the input->output mapping
      * for a few sample points would be: 0 -> 0, 0.15 ->
      * 0.25, 0.3 -> 0.5, 0.5 -> 0.64
@@ -913,6 +949,13 @@
      * compensation, the HAL must report whether setting the
      * black level lock was successful in the output result
      * metadata.
+     * </p><p>
+     * The black level locking must happen at the sensor, and not at the ISP.
+     * If for some reason black level locking is no longer legal (for example,
+     * the analog gain has changed, which forces black levels to be
+     * recalculated), then the HAL is free to override this request (and it
+     * must report 'OFF' when this does happen) until the next time locking
+     * is legal again.
      * </p>
      */
     public static final Key<Boolean> BLACK_LEVEL_LOCK =
diff --git a/core/java/android/hardware/camera2/CaptureRequestKeys.java b/core/java/android/hardware/camera2/CaptureRequestKeys.java
deleted file mode 100644
index 17de8f0..0000000
--- a/core/java/android/hardware/camera2/CaptureRequestKeys.java
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.camera2;
-
-import static android.hardware.camera2.CameraMetadata.Key;
-
-/**
- * ! Do not edit this file directly !
- *
- * Generated automatically from CaptureRequestKeys.mako
- *
- * TODO: Include a hash of the input files here that the build can check.
- */
-
-/**
- * The base class for camera controls and information.
- *
- * This class defines the basic key/value map used for querying for camera
- * characteristics or capture results, and for setting camera request
- * parameters.
- *
- * @see CaptureRequest
- * @see CameraMetadata
- * @hide
- **/
-public final class CaptureRequestKeys {
-    public static final class ColorCorrection {
-
-            public static final class ModeKey extends Key<ColorCorrection.ModeKey.Enum> {
-                public enum Enum {
-                    TRANSFORM_MATRIX,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum TRANSFORM_MATRIX = Enum.TRANSFORM_MATRIX;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, ColorCorrection.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<ColorCorrection.ModeKey.Enum> MODE =
-                new ModeKey("android.colorCorrection.mode");
-        public static final Key<Rational[]> TRANSFORM =
-                new Key<Rational[]>("android.colorCorrection.transform", Rational[].class);
-        public static final Key<float[]> GAINS =
-                new Key<float[]>("android.colorCorrection.gains", float[].class);
-
-    }
-
-    public static final class Control {
-
-            public static final class AeAntibandingModeKey extends Key<Control.AeAntibandingModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    _50HZ,
-                    _60HZ,
-                    AUTO;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum _50HZ = Enum._50HZ;
-                public static final Enum _60HZ = Enum._60HZ;
-                public static final Enum AUTO = Enum.AUTO;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AeAntibandingModeKey(String name) {
-                    super(name, Control.AeAntibandingModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AeAntibandingModeKey.Enum> AE_ANTIBANDING_MODE =
-                new AeAntibandingModeKey("android.control.aeAntibandingMode");
-        public static final Key<Integer> AE_EXPOSURE_COMPENSATION =
-                new Key<Integer>("android.control.aeExposureCompensation", int.class);
-        public static final Key<Boolean> AE_LOCK =
-                new Key<Boolean>("android.control.aeLock", boolean.class);
-
-            public static final class AeModeKey extends Key<Control.AeModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    ON,
-                    ON_AUTO_FLASH,
-                    ON_ALWAYS_FLASH,
-                    ON_AUTO_FLASH_REDEYE;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum ON = Enum.ON;
-                public static final Enum ON_AUTO_FLASH = Enum.ON_AUTO_FLASH;
-                public static final Enum ON_ALWAYS_FLASH = Enum.ON_ALWAYS_FLASH;
-                public static final Enum ON_AUTO_FLASH_REDEYE = Enum.ON_AUTO_FLASH_REDEYE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AeModeKey(String name) {
-                    super(name, Control.AeModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AeModeKey.Enum> AE_MODE =
-                new AeModeKey("android.control.aeMode");
-        public static final Key<int[]> AE_REGIONS =
-                new Key<int[]>("android.control.aeRegions", int[].class);
-        public static final Key<int[]> AE_TARGET_FPS_RANGE =
-                new Key<int[]>("android.control.aeTargetFpsRange", int[].class);
-
-            public static final class AePrecaptureTriggerKey extends Key<Control.AePrecaptureTriggerKey.Enum> {
-                public enum Enum {
-                    IDLE,
-                    START;
-                }
-
-                public static final Enum IDLE = Enum.IDLE;
-                public static final Enum START = Enum.START;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AePrecaptureTriggerKey(String name) {
-                    super(name, Control.AePrecaptureTriggerKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AePrecaptureTriggerKey.Enum> AE_PRECAPTURE_TRIGGER =
-                new AePrecaptureTriggerKey("android.control.aePrecaptureTrigger");
-
-            public static final class AfModeKey extends Key<Control.AfModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    AUTO,
-                    MACRO,
-                    CONTINUOUS_VIDEO,
-                    CONTINUOUS_PICTURE,
-                    EDOF;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum AUTO = Enum.AUTO;
-                public static final Enum MACRO = Enum.MACRO;
-                public static final Enum CONTINUOUS_VIDEO = Enum.CONTINUOUS_VIDEO;
-                public static final Enum CONTINUOUS_PICTURE = Enum.CONTINUOUS_PICTURE;
-                public static final Enum EDOF = Enum.EDOF;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AfModeKey(String name) {
-                    super(name, Control.AfModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AfModeKey.Enum> AF_MODE =
-                new AfModeKey("android.control.afMode");
-        public static final Key<int[]> AF_REGIONS =
-                new Key<int[]>("android.control.afRegions", int[].class);
-
-            public static final class AfTriggerKey extends Key<Control.AfTriggerKey.Enum> {
-                public enum Enum {
-                    IDLE,
-                    START,
-                    CANCEL;
-                }
-
-                public static final Enum IDLE = Enum.IDLE;
-                public static final Enum START = Enum.START;
-                public static final Enum CANCEL = Enum.CANCEL;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AfTriggerKey(String name) {
-                    super(name, Control.AfTriggerKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AfTriggerKey.Enum> AF_TRIGGER =
-                new AfTriggerKey("android.control.afTrigger");
-        public static final Key<Boolean> AWB_LOCK =
-                new Key<Boolean>("android.control.awbLock", boolean.class);
-
-            public static final class AwbModeKey extends Key<Control.AwbModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    AUTO,
-                    INCANDESCENT,
-                    FLUORESCENT,
-                    WARM_FLUORESCENT,
-                    DAYLIGHT,
-                    CLOUDY_DAYLIGHT,
-                    TWILIGHT,
-                    SHADE;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum AUTO = Enum.AUTO;
-                public static final Enum INCANDESCENT = Enum.INCANDESCENT;
-                public static final Enum FLUORESCENT = Enum.FLUORESCENT;
-                public static final Enum WARM_FLUORESCENT = Enum.WARM_FLUORESCENT;
-                public static final Enum DAYLIGHT = Enum.DAYLIGHT;
-                public static final Enum CLOUDY_DAYLIGHT = Enum.CLOUDY_DAYLIGHT;
-                public static final Enum TWILIGHT = Enum.TWILIGHT;
-                public static final Enum SHADE = Enum.SHADE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AwbModeKey(String name) {
-                    super(name, Control.AwbModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AwbModeKey.Enum> AWB_MODE =
-                new AwbModeKey("android.control.awbMode");
-        public static final Key<int[]> AWB_REGIONS =
-                new Key<int[]>("android.control.awbRegions", int[].class);
-
-            public static final class CaptureIntentKey extends Key<Control.CaptureIntentKey.Enum> {
-                public enum Enum {
-                    CUSTOM,
-                    PREVIEW,
-                    STILL_CAPTURE,
-                    VIDEO_RECORD,
-                    VIDEO_SNAPSHOT,
-                    ZERO_SHUTTER_LAG;
-                }
-
-                public static final Enum CUSTOM = Enum.CUSTOM;
-                public static final Enum PREVIEW = Enum.PREVIEW;
-                public static final Enum STILL_CAPTURE = Enum.STILL_CAPTURE;
-                public static final Enum VIDEO_RECORD = Enum.VIDEO_RECORD;
-                public static final Enum VIDEO_SNAPSHOT = Enum.VIDEO_SNAPSHOT;
-                public static final Enum ZERO_SHUTTER_LAG = Enum.ZERO_SHUTTER_LAG;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private CaptureIntentKey(String name) {
-                    super(name, Control.CaptureIntentKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.CaptureIntentKey.Enum> CAPTURE_INTENT =
-                new CaptureIntentKey("android.control.captureIntent");
-
-            public static final class EffectModeKey extends Key<Control.EffectModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    MONO,
-                    NEGATIVE,
-                    SOLARIZE,
-                    SEPIA,
-                    POSTERIZE,
-                    WHITEBOARD,
-                    BLACKBOARD,
-                    AQUA;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum MONO = Enum.MONO;
-                public static final Enum NEGATIVE = Enum.NEGATIVE;
-                public static final Enum SOLARIZE = Enum.SOLARIZE;
-                public static final Enum SEPIA = Enum.SEPIA;
-                public static final Enum POSTERIZE = Enum.POSTERIZE;
-                public static final Enum WHITEBOARD = Enum.WHITEBOARD;
-                public static final Enum BLACKBOARD = Enum.BLACKBOARD;
-                public static final Enum AQUA = Enum.AQUA;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private EffectModeKey(String name) {
-                    super(name, Control.EffectModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.EffectModeKey.Enum> EFFECT_MODE =
-                new EffectModeKey("android.control.effectMode");
-
-            public static final class ModeKey extends Key<Control.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    AUTO,
-                    USE_SCENE_MODE;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum AUTO = Enum.AUTO;
-                public static final Enum USE_SCENE_MODE = Enum.USE_SCENE_MODE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Control.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.ModeKey.Enum> MODE =
-                new ModeKey("android.control.mode");
-
-            public static final class SceneModeKey extends Key<Control.SceneModeKey.Enum> {
-                public enum Enum {
-                    UNSUPPORTED,
-                    FACE_PRIORITY,
-                    ACTION,
-                    PORTRAIT,
-                    LANDSCAPE,
-                    NIGHT,
-                    NIGHT_PORTRAIT,
-                    THEATRE,
-                    BEACH,
-                    SNOW,
-                    SUNSET,
-                    STEADYPHOTO,
-                    FIREWORKS,
-                    SPORTS,
-                    PARTY,
-                    CANDLELIGHT,
-                    BARCODE;
-                }
-
-                public static final Enum UNSUPPORTED = Enum.UNSUPPORTED;
-                public static final Enum FACE_PRIORITY = Enum.FACE_PRIORITY;
-                public static final Enum ACTION = Enum.ACTION;
-                public static final Enum PORTRAIT = Enum.PORTRAIT;
-                public static final Enum LANDSCAPE = Enum.LANDSCAPE;
-                public static final Enum NIGHT = Enum.NIGHT;
-                public static final Enum NIGHT_PORTRAIT = Enum.NIGHT_PORTRAIT;
-                public static final Enum THEATRE = Enum.THEATRE;
-                public static final Enum BEACH = Enum.BEACH;
-                public static final Enum SNOW = Enum.SNOW;
-                public static final Enum SUNSET = Enum.SUNSET;
-                public static final Enum STEADYPHOTO = Enum.STEADYPHOTO;
-                public static final Enum FIREWORKS = Enum.FIREWORKS;
-                public static final Enum SPORTS = Enum.SPORTS;
-                public static final Enum PARTY = Enum.PARTY;
-                public static final Enum CANDLELIGHT = Enum.CANDLELIGHT;
-                public static final Enum BARCODE = Enum.BARCODE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private SceneModeKey(String name) {
-                    super(name, Control.SceneModeKey.Enum.class);
-                }
-
-                static {
-                    CameraMetadata.registerEnumValues(Control.SceneModeKey.Enum.class, new int[] {
-                        0,  // UNSUPPORTED
-                        1,  // FACE_PRIORITY
-                        2,  // ACTION
-                        3,  // PORTRAIT
-                        4,  // LANDSCAPE
-                        5,  // NIGHT
-                        6,  // NIGHT_PORTRAIT
-                        7,  // THEATRE
-                        8,  // BEACH
-                        9,  // SNOW
-                        10,  // SUNSET
-                        11,  // STEADYPHOTO
-                        12,  // FIREWORKS
-                        13,  // SPORTS
-                        14,  // PARTY
-                        15,  // CANDLELIGHT
-                        16  // BARCODE
-                    });
-                }
-            }
-
-        public static final Key<Control.SceneModeKey.Enum> SCENE_MODE =
-                new SceneModeKey("android.control.sceneMode");
-        public static final Key<Boolean> VIDEO_STABILIZATION_MODE =
-                new Key<Boolean>("android.control.videoStabilizationMode", boolean.class);
-
-    }
-
-    public static final class Edge {
-
-            public static final class ModeKey extends Key<Edge.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Edge.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Edge.ModeKey.Enum> MODE =
-                new ModeKey("android.edge.mode");
-
-    }
-
-    public static final class Flash {
-
-            public static final class ModeKey extends Key<Flash.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    SINGLE,
-                    TORCH;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum SINGLE = Enum.SINGLE;
-                public static final Enum TORCH = Enum.TORCH;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Flash.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Flash.ModeKey.Enum> MODE =
-                new ModeKey("android.flash.mode");
-
-    }
-
-    public static final class Jpeg {
-        public static final Key<double[]> GPS_COORDINATES =
-                new Key<double[]>("android.jpeg.gpsCoordinates", double[].class);
-        public static final Key<String> GPS_PROCESSING_METHOD =
-                new Key<String>("android.jpeg.gpsProcessingMethod", String.class);
-        public static final Key<Long> GPS_TIMESTAMP =
-                new Key<Long>("android.jpeg.gpsTimestamp", long.class);
-        public static final Key<Integer> ORIENTATION =
-                new Key<Integer>("android.jpeg.orientation", int.class);
-        public static final Key<Byte> QUALITY =
-                new Key<Byte>("android.jpeg.quality", byte.class);
-        public static final Key<Byte> THUMBNAIL_QUALITY =
-                new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
-        public static final Key<android.hardware.camera2.Size> THUMBNAIL_SIZE =
-                new Key<android.hardware.camera2.Size>("android.jpeg.thumbnailSize", android.hardware.camera2.Size.class);
-
-    }
-
-    public static final class Lens {
-        public static final Key<Float> APERTURE =
-                new Key<Float>("android.lens.aperture", float.class);
-        public static final Key<Float> FILTER_DENSITY =
-                new Key<Float>("android.lens.filterDensity", float.class);
-        public static final Key<Float> FOCAL_LENGTH =
-                new Key<Float>("android.lens.focalLength", float.class);
-        public static final Key<Float> FOCUS_DISTANCE =
-                new Key<Float>("android.lens.focusDistance", float.class);
-
-            public static final class OpticalStabilizationModeKey extends Key<Lens.OpticalStabilizationModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    ON;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum ON = Enum.ON;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private OpticalStabilizationModeKey(String name) {
-                    super(name, Lens.OpticalStabilizationModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Lens.OpticalStabilizationModeKey.Enum> OPTICAL_STABILIZATION_MODE =
-                new OpticalStabilizationModeKey("android.lens.opticalStabilizationMode");
-
-    }
-
-    public static final class NoiseReduction {
-
-            public static final class ModeKey extends Key<NoiseReduction.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, NoiseReduction.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<NoiseReduction.ModeKey.Enum> MODE =
-                new ModeKey("android.noiseReduction.mode");
-
-    }
-
-    /**
-     * @hide
-     */
-    public static final class Request {
-        /**
-         * @hide
-         */
-        public static final Key<Integer> ID =
-                new Key<Integer>("android.request.id", int.class);
-
-    }
-
-    public static final class Scaler {
-        public static final Key<android.graphics.Rect> CROP_REGION =
-                new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
-
-    }
-
-    public static final class Sensor {
-        public static final Key<Long> EXPOSURE_TIME =
-                new Key<Long>("android.sensor.exposureTime", long.class);
-        public static final Key<Long> FRAME_DURATION =
-                new Key<Long>("android.sensor.frameDuration", long.class);
-        public static final Key<Integer> SENSITIVITY =
-                new Key<Integer>("android.sensor.sensitivity", int.class);
-
-    }
-
-    public static final class Statistics {
-
-            public static final class FaceDetectModeKey extends Key<Statistics.FaceDetectModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    SIMPLE,
-                    FULL;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum SIMPLE = Enum.SIMPLE;
-                public static final Enum FULL = Enum.FULL;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private FaceDetectModeKey(String name) {
-                    super(name, Statistics.FaceDetectModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Statistics.FaceDetectModeKey.Enum> FACE_DETECT_MODE =
-                new FaceDetectModeKey("android.statistics.faceDetectMode");
-
-    }
-
-    public static final class Tonemap {
-        public static final Key<Float> CURVE_BLUE =
-                new Key<Float>("android.tonemap.curveBlue", float.class);
-        public static final Key<Float> CURVE_GREEN =
-                new Key<Float>("android.tonemap.curveGreen", float.class);
-        public static final Key<float[]> CURVE_RED =
-                new Key<float[]>("android.tonemap.curveRed", float[].class);
-
-            public static final class ModeKey extends Key<Tonemap.ModeKey.Enum> {
-                public enum Enum {
-                    CONTRAST_CURVE,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum CONTRAST_CURVE = Enum.CONTRAST_CURVE;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Tonemap.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Tonemap.ModeKey.Enum> MODE =
-                new ModeKey("android.tonemap.mode");
-
-    }
-
-    /**
-     * @hide
-     */
-    public static final class Led {
-        /**
-         * @hide
-         */
-        public static final Key<Boolean> TRANSMIT =
-                new Key<Boolean>("android.led.transmit", boolean.class);
-
-    }
-
-    public static final class BlackLevel {
-        public static final Key<Boolean> LOCK =
-                new Key<Boolean>("android.blackLevel.lock", boolean.class);
-
-    }
-
-}
-
-
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 31377be..ef6aaa0 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -138,7 +138,8 @@
      * This matrix is either set by HAL when the request
      * android.colorCorrection.mode is not TRANSFORM_MATRIX, or
      * directly by the application in the request when the
-     * androird.colorCorrection.mode is TRANSFORM_MATRIX.
+     * android.colorCorrection.mode is TRANSFORM_MATRIX.
+     * </p><p>
      * In the latter case, the HAL may round the matrix to account
      * for precision issues; the final rounded matrix should be
      * reported back in this matrix result metadata.
@@ -161,6 +162,11 @@
      * it should use the G_even value,and write G_odd equal to
      * G_even in the output result metadata.
      * </p><p>
+     * This array is either set by HAL when the request
+     * android.colorCorrection.mode is not TRANSFORM_MATRIX, or
+     * directly by the application in the request when the
+     * android.colorCorrection.mode is TRANSFORM_MATRIX.
+     * </p><p>
      * The ouput should be the gains actually applied by the HAL to
      * the current frame.
      * </p>
@@ -651,7 +657,10 @@
     /**
      * <p>
      * Duration each pixel is exposed to
-     * light
+     * light.
+     * </p><p>
+     * If the sensor can't expose this exact duration, it should shorten the
+     * duration exposed to the nearest possible value (rather than expose longer).
      * </p>
      * <p>
      * 1/10000 - 30 sec range. No bulb mode
@@ -678,6 +687,9 @@
      * Gain applied to image data. Must be
      * implemented through analog gain only if set to values
      * below 'maximum analog sensitivity'.
+     * </p><p>
+     * If the sensor can't apply this exact gain, it should lessen the
+     * gain to the nearest possible value (rather than gain more).
      * </p>
      * <p>
      * ISO 12232:2006 REI method
@@ -701,6 +713,18 @@
 
     /**
      * <p>
+     * The temperature of the sensor, sampled at the time
+     * exposure began for this frame.
+     * </p><p>
+     * The thermal diode being queried should be inside the sensor PCB, or
+     * somewhere close to it.
+     * </p>
+     */
+    public static final Key<Float> SENSOR_TEMPERATURE =
+            new Key<Float>("android.sensor.temperature", float.class);
+
+    /**
+     * <p>
      * State of the face detector
      * unit
      * </p>
@@ -759,7 +783,8 @@
      * detected faces
      * </p>
      * <p>
-     * Only available if faceDetectMode != OFF
+     * Only available if faceDetectMode != OFF. The value should be
+     * meaningful (for example, setting 100 at all times is illegal).
      * </p>
      */
     public static final Key<byte[]> STATISTICS_FACE_SCORES =
@@ -776,6 +801,9 @@
      * of 1; all other sections should have gains above 1.
      * the map should be on the order of 30-40 rows, and
      * must be smaller than 64x64.
+     * </p><p>
+     * When android.colorCorrection.mode = TRANSFORM_MATRIX, the map
+     * must take into account the colorCorrection settings.
      * </p>
      */
     public static final Key<float[]> STATISTICS_LENS_SHADING_MAP =
@@ -794,6 +822,9 @@
      * </p><p>
      * The 4 channel gains are defined in Bayer domain,
      * see android.colorCorrection.gains for details.
+     * </p><p>
+     * This value should always be calculated by the AWB block,
+     * regardless of the android.control.* current values.
      * </p>
      */
     public static final Key<float[]> STATISTICS_PREDICTED_COLOR_GAINS =
@@ -817,6 +848,9 @@
      * </p><p>
      * These estimates must be provided for all frames, even if
      * capture settings and color transforms are set by the application.
+     * </p><p>
+     * This value should always be calculated by the AWB block,
+     * regardless of the android.control.* current values.
      * </p>
      */
     public static final Key<Rational[]> STATISTICS_PREDICTED_COLOR_TRANSFORM =
@@ -843,18 +877,30 @@
      * Table mapping blue input values to output
      * values
      * </p>
+     * <p>
+     * Tonemapping / contrast / gamma curve for the blue
+     * channel, to use when android.tonemap.mode is CONTRAST_CURVE.
+     * </p><p>
+     * See android.tonemap.curveRed for more details.
+     * </p>
      */
-    public static final Key<Float> TONEMAP_CURVE_BLUE =
-            new Key<Float>("android.tonemap.curveBlue", float.class);
+    public static final Key<float[]> TONEMAP_CURVE_BLUE =
+            new Key<float[]>("android.tonemap.curveBlue", float[].class);
 
     /**
      * <p>
      * Table mapping green input values to output
      * values
      * </p>
+     * <p>
+     * Tonemapping / contrast / gamma curve for the green
+     * channel, to use when android.tonemap.mode is CONTRAST_CURVE.
+     * </p><p>
+     * See android.tonemap.curveRed for more details.
+     * </p>
      */
-    public static final Key<Float> TONEMAP_CURVE_GREEN =
-            new Key<Float>("android.tonemap.curveGreen", float.class);
+    public static final Key<float[]> TONEMAP_CURVE_GREEN =
+            new Key<float[]>("android.tonemap.curveGreen", float[].class);
 
     /**
      * <p>
@@ -862,9 +908,17 @@
      * values
      * </p>
      * <p>
-     * .The input range must be monotonically increasing
-     * with N, and values between entries should be linearly
-     * interpolated. For example, if the array is: [0.0, 0.0,
+     * Tonemapping / contrast / gamma curve for the red
+     * channel, to use when android.tonemap.mode is CONTRAST_CURVE.
+     * </p><p>
+     * Since the input and output ranges may vary depending on
+     * the camera pipeline, the input and output pixel values
+     * are represented by normalized floating-point values
+     * between 0 and 1, with 0 == black and 1 == white.
+     * </p><p>
+     * The curve should be linearly interpolated between the
+     * defined points. The points will be listed in increasing
+     * order of P_IN. For example, if the array is: [0.0, 0.0,
      * 0.3, 0.5, 1.0, 1.0], then the input->output mapping
      * for a few sample points would be: 0 -> 0, 0.15 ->
      * 0.25, 0.3 -> 0.5, 0.5 -> 0.64
@@ -917,6 +971,13 @@
      * compensation, the HAL must report whether setting the
      * black level lock was successful in the output result
      * metadata.
+     * </p><p>
+     * The black level locking must happen at the sensor, and not at the ISP.
+     * If for some reason black level locking is no longer legal (for example,
+     * the analog gain has changed, which forces black levels to be
+     * recalculated), then the HAL is free to override this request (and it
+     * must report 'OFF' when this does happen) until the next time locking
+     * is legal again.
      * </p>
      */
     public static final Key<Boolean> BLACK_LEVEL_LOCK =
diff --git a/core/java/android/hardware/camera2/CaptureResultKeys.java b/core/java/android/hardware/camera2/CaptureResultKeys.java
deleted file mode 100644
index dd3ed83..0000000
--- a/core/java/android/hardware/camera2/CaptureResultKeys.java
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.camera2;
-
-import static android.hardware.camera2.CameraMetadata.Key;
-
-/**
- * ! Do not edit this file directly !
- *
- * Generated automatically from CaptureResultKeys.mako
- *
- * TODO: Include a hash of the input files here that the build can check.
- */
-
-/**
- * The base class for camera controls and information.
- *
- * This class defines the basic key/value map used for querying for camera
- * characteristics or capture results, and for setting camera request
- * parameters.
- *
- * @see CaptureResult
- * @see CameraMetadata
- * @hide
- **/
-public final class CaptureResultKeys {
-    public static final class ColorCorrection {
-        public static final Key<Rational[]> TRANSFORM =
-                new Key<Rational[]>("android.colorCorrection.transform", Rational[].class);
-        public static final Key<float[]> GAINS =
-                new Key<float[]>("android.colorCorrection.gains", float[].class);
-
-    }
-
-    public static final class Control {
-        /**
-         * @hide
-         */
-        public static final Key<Integer> AE_PRECAPTURE_ID =
-                new Key<Integer>("android.control.aePrecaptureId", int.class);
-        public static final Key<int[]> AE_REGIONS =
-                new Key<int[]>("android.control.aeRegions", int[].class);
-
-            public static final class AeStateKey extends Key<Control.AeStateKey.Enum> {
-                public enum Enum {
-                    INACTIVE,
-                    SEARCHING,
-                    CONVERGED,
-                    LOCKED,
-                    FLASH_REQUIRED,
-                    PRECAPTURE;
-                }
-
-                public static final Enum INACTIVE = Enum.INACTIVE;
-                public static final Enum SEARCHING = Enum.SEARCHING;
-                public static final Enum CONVERGED = Enum.CONVERGED;
-                public static final Enum LOCKED = Enum.LOCKED;
-                public static final Enum FLASH_REQUIRED = Enum.FLASH_REQUIRED;
-                public static final Enum PRECAPTURE = Enum.PRECAPTURE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AeStateKey(String name) {
-                    super(name, Control.AeStateKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AeStateKey.Enum> AE_STATE =
-                new AeStateKey("android.control.aeState");
-
-            public static final class AfModeKey extends Key<Control.AfModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    AUTO,
-                    MACRO,
-                    CONTINUOUS_VIDEO,
-                    CONTINUOUS_PICTURE,
-                    EDOF;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum AUTO = Enum.AUTO;
-                public static final Enum MACRO = Enum.MACRO;
-                public static final Enum CONTINUOUS_VIDEO = Enum.CONTINUOUS_VIDEO;
-                public static final Enum CONTINUOUS_PICTURE = Enum.CONTINUOUS_PICTURE;
-                public static final Enum EDOF = Enum.EDOF;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AfModeKey(String name) {
-                    super(name, Control.AfModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AfModeKey.Enum> AF_MODE =
-                new AfModeKey("android.control.afMode");
-        public static final Key<int[]> AF_REGIONS =
-                new Key<int[]>("android.control.afRegions", int[].class);
-
-            public static final class AfStateKey extends Key<Control.AfStateKey.Enum> {
-                public enum Enum {
-                    INACTIVE,
-                    PASSIVE_SCAN,
-                    PASSIVE_FOCUSED,
-                    ACTIVE_SCAN,
-                    FOCUSED_LOCKED,
-                    NOT_FOCUSED_LOCKED;
-                }
-
-                public static final Enum INACTIVE = Enum.INACTIVE;
-                public static final Enum PASSIVE_SCAN = Enum.PASSIVE_SCAN;
-                public static final Enum PASSIVE_FOCUSED = Enum.PASSIVE_FOCUSED;
-                public static final Enum ACTIVE_SCAN = Enum.ACTIVE_SCAN;
-                public static final Enum FOCUSED_LOCKED = Enum.FOCUSED_LOCKED;
-                public static final Enum NOT_FOCUSED_LOCKED = Enum.NOT_FOCUSED_LOCKED;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AfStateKey(String name) {
-                    super(name, Control.AfStateKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AfStateKey.Enum> AF_STATE =
-                new AfStateKey("android.control.afState");
-        /**
-         * @hide
-         */
-        public static final Key<Integer> AF_TRIGGER_ID =
-                new Key<Integer>("android.control.afTriggerId", int.class);
-
-            public static final class AwbModeKey extends Key<Control.AwbModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    AUTO,
-                    INCANDESCENT,
-                    FLUORESCENT,
-                    WARM_FLUORESCENT,
-                    DAYLIGHT,
-                    CLOUDY_DAYLIGHT,
-                    TWILIGHT,
-                    SHADE;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum AUTO = Enum.AUTO;
-                public static final Enum INCANDESCENT = Enum.INCANDESCENT;
-                public static final Enum FLUORESCENT = Enum.FLUORESCENT;
-                public static final Enum WARM_FLUORESCENT = Enum.WARM_FLUORESCENT;
-                public static final Enum DAYLIGHT = Enum.DAYLIGHT;
-                public static final Enum CLOUDY_DAYLIGHT = Enum.CLOUDY_DAYLIGHT;
-                public static final Enum TWILIGHT = Enum.TWILIGHT;
-                public static final Enum SHADE = Enum.SHADE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AwbModeKey(String name) {
-                    super(name, Control.AwbModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AwbModeKey.Enum> AWB_MODE =
-                new AwbModeKey("android.control.awbMode");
-        public static final Key<int[]> AWB_REGIONS =
-                new Key<int[]>("android.control.awbRegions", int[].class);
-
-            public static final class AwbStateKey extends Key<Control.AwbStateKey.Enum> {
-                public enum Enum {
-                    INACTIVE,
-                    SEARCHING,
-                    CONVERGED,
-                    LOCKED;
-                }
-
-                public static final Enum INACTIVE = Enum.INACTIVE;
-                public static final Enum SEARCHING = Enum.SEARCHING;
-                public static final Enum CONVERGED = Enum.CONVERGED;
-                public static final Enum LOCKED = Enum.LOCKED;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private AwbStateKey(String name) {
-                    super(name, Control.AwbStateKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.AwbStateKey.Enum> AWB_STATE =
-                new AwbStateKey("android.control.awbState");
-
-            public static final class ModeKey extends Key<Control.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    AUTO,
-                    USE_SCENE_MODE;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum AUTO = Enum.AUTO;
-                public static final Enum USE_SCENE_MODE = Enum.USE_SCENE_MODE;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Control.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Control.ModeKey.Enum> MODE =
-                new ModeKey("android.control.mode");
-
-    }
-
-    public static final class Edge {
-
-            public static final class ModeKey extends Key<Edge.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Edge.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Edge.ModeKey.Enum> MODE =
-                new ModeKey("android.edge.mode");
-
-    }
-
-    public static final class Flash {
-
-            public static final class ModeKey extends Key<Flash.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    SINGLE,
-                    TORCH;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum SINGLE = Enum.SINGLE;
-                public static final Enum TORCH = Enum.TORCH;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Flash.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Flash.ModeKey.Enum> MODE =
-                new ModeKey("android.flash.mode");
-
-            public static final class StateKey extends Key<Flash.StateKey.Enum> {
-                public enum Enum {
-                    UNAVAILABLE,
-                    CHARGING,
-                    READY,
-                    FIRED;
-                }
-
-                public static final Enum UNAVAILABLE = Enum.UNAVAILABLE;
-                public static final Enum CHARGING = Enum.CHARGING;
-                public static final Enum READY = Enum.READY;
-                public static final Enum FIRED = Enum.FIRED;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private StateKey(String name) {
-                    super(name, Flash.StateKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Flash.StateKey.Enum> STATE =
-                new StateKey("android.flash.state");
-
-    }
-
-    public static final class Jpeg {
-        public static final Key<double[]> GPS_COORDINATES =
-                new Key<double[]>("android.jpeg.gpsCoordinates", double[].class);
-        public static final Key<String> GPS_PROCESSING_METHOD =
-                new Key<String>("android.jpeg.gpsProcessingMethod", String.class);
-        public static final Key<Long> GPS_TIMESTAMP =
-                new Key<Long>("android.jpeg.gpsTimestamp", long.class);
-        public static final Key<Integer> ORIENTATION =
-                new Key<Integer>("android.jpeg.orientation", int.class);
-        public static final Key<Byte> QUALITY =
-                new Key<Byte>("android.jpeg.quality", byte.class);
-        public static final Key<Byte> THUMBNAIL_QUALITY =
-                new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
-        public static final Key<android.hardware.camera2.Size> THUMBNAIL_SIZE =
-                new Key<android.hardware.camera2.Size>("android.jpeg.thumbnailSize", android.hardware.camera2.Size.class);
-
-    }
-
-    public static final class Lens {
-        public static final Key<Float> APERTURE =
-                new Key<Float>("android.lens.aperture", float.class);
-        public static final Key<Float> FILTER_DENSITY =
-                new Key<Float>("android.lens.filterDensity", float.class);
-        public static final Key<Float> FOCAL_LENGTH =
-                new Key<Float>("android.lens.focalLength", float.class);
-        public static final Key<Float> FOCUS_DISTANCE =
-                new Key<Float>("android.lens.focusDistance", float.class);
-        public static final Key<Float> FOCUS_RANGE =
-                new Key<Float>("android.lens.focusRange", float.class);
-
-            public static final class OpticalStabilizationModeKey extends Key<Lens.OpticalStabilizationModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    ON;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum ON = Enum.ON;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private OpticalStabilizationModeKey(String name) {
-                    super(name, Lens.OpticalStabilizationModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Lens.OpticalStabilizationModeKey.Enum> OPTICAL_STABILIZATION_MODE =
-                new OpticalStabilizationModeKey("android.lens.opticalStabilizationMode");
-
-            public static final class StateKey extends Key<Lens.StateKey.Enum> {
-                public enum Enum {
-                    STATIONARY;
-                }
-
-                public static final Enum STATIONARY = Enum.STATIONARY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private StateKey(String name) {
-                    super(name, Lens.StateKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Lens.StateKey.Enum> STATE =
-                new StateKey("android.lens.state");
-
-    }
-
-    public static final class NoiseReduction {
-
-            public static final class ModeKey extends Key<NoiseReduction.ModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, NoiseReduction.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<NoiseReduction.ModeKey.Enum> MODE =
-                new ModeKey("android.noiseReduction.mode");
-
-    }
-
-    public static final class Request {
-        public static final Key<Integer> FRAME_COUNT =
-                new Key<Integer>("android.request.frameCount", int.class);
-        /**
-         * @hide
-         */
-        public static final Key<Integer> ID =
-                new Key<Integer>("android.request.id", int.class);
-
-    }
-
-    public static final class Scaler {
-        public static final Key<android.graphics.Rect> CROP_REGION =
-                new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
-
-    }
-
-    public static final class Sensor {
-        public static final Key<Long> EXPOSURE_TIME =
-                new Key<Long>("android.sensor.exposureTime", long.class);
-        public static final Key<Long> FRAME_DURATION =
-                new Key<Long>("android.sensor.frameDuration", long.class);
-        public static final Key<Integer> SENSITIVITY =
-                new Key<Integer>("android.sensor.sensitivity", int.class);
-        public static final Key<Long> TIMESTAMP =
-                new Key<Long>("android.sensor.timestamp", long.class);
-
-    }
-
-    public static final class Statistics {
-
-            public static final class FaceDetectModeKey extends Key<Statistics.FaceDetectModeKey.Enum> {
-                public enum Enum {
-                    OFF,
-                    SIMPLE,
-                    FULL;
-                }
-
-                public static final Enum OFF = Enum.OFF;
-                public static final Enum SIMPLE = Enum.SIMPLE;
-                public static final Enum FULL = Enum.FULL;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private FaceDetectModeKey(String name) {
-                    super(name, Statistics.FaceDetectModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Statistics.FaceDetectModeKey.Enum> FACE_DETECT_MODE =
-                new FaceDetectModeKey("android.statistics.faceDetectMode");
-        public static final Key<int[]> FACE_IDS =
-                new Key<int[]>("android.statistics.faceIds", int[].class);
-        public static final Key<int[]> FACE_LANDMARKS =
-                new Key<int[]>("android.statistics.faceLandmarks", int[].class);
-        public static final Key<android.graphics.Rect[]> FACE_RECTANGLES =
-                new Key<android.graphics.Rect[]>("android.statistics.faceRectangles", android.graphics.Rect[].class);
-        public static final Key<byte[]> FACE_SCORES =
-                new Key<byte[]>("android.statistics.faceScores", byte[].class);
-        public static final Key<float[]> LENS_SHADING_MAP =
-                new Key<float[]>("android.statistics.lensShadingMap", float[].class);
-        public static final Key<float[]> PREDICTED_COLOR_GAINS =
-                new Key<float[]>("android.statistics.predictedColorGains", float[].class);
-        public static final Key<Rational[]> PREDICTED_COLOR_TRANSFORM =
-                new Key<Rational[]>("android.statistics.predictedColorTransform", Rational[].class);
-
-            public static final class SceneFlickerKey extends Key<Statistics.SceneFlickerKey.Enum> {
-                public enum Enum {
-                    NONE,
-                    _50HZ,
-                    _60HZ;
-                }
-
-                public static final Enum NONE = Enum.NONE;
-                public static final Enum _50HZ = Enum._50HZ;
-                public static final Enum _60HZ = Enum._60HZ;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private SceneFlickerKey(String name) {
-                    super(name, Statistics.SceneFlickerKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Statistics.SceneFlickerKey.Enum> SCENE_FLICKER =
-                new SceneFlickerKey("android.statistics.sceneFlicker");
-
-    }
-
-    public static final class Tonemap {
-        public static final Key<Float> CURVE_BLUE =
-                new Key<Float>("android.tonemap.curveBlue", float.class);
-        public static final Key<Float> CURVE_GREEN =
-                new Key<Float>("android.tonemap.curveGreen", float.class);
-        public static final Key<float[]> CURVE_RED =
-                new Key<float[]>("android.tonemap.curveRed", float[].class);
-
-            public static final class ModeKey extends Key<Tonemap.ModeKey.Enum> {
-                public enum Enum {
-                    CONTRAST_CURVE,
-                    FAST,
-                    HIGH_QUALITY;
-                }
-
-                public static final Enum CONTRAST_CURVE = Enum.CONTRAST_CURVE;
-                public static final Enum FAST = Enum.FAST;
-                public static final Enum HIGH_QUALITY = Enum.HIGH_QUALITY;
-
-                // TODO: remove requirement for constructor by making Key an interface
-                private ModeKey(String name) {
-                    super(name, Tonemap.ModeKey.Enum.class);
-                }
-
-            }
-
-        public static final Key<Tonemap.ModeKey.Enum> MODE =
-                new ModeKey("android.tonemap.mode");
-
-    }
-
-    /**
-     * @hide
-     */
-    public static final class Led {
-        /**
-         * @hide
-         */
-        public static final Key<Boolean> TRANSMIT =
-                new Key<Boolean>("android.led.transmit", boolean.class);
-
-    }
-
-    public static final class BlackLevel {
-        public static final Key<Boolean> LOCK =
-                new Key<Boolean>("android.blackLevel.lock", boolean.class);
-
-    }
-
-}
-
-
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index fa79051..1fb690e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -24,6 +24,7 @@
 import android.hardware.camera2.CameraProperties;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.utils.CameraRuntimeException;
+import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
@@ -67,7 +68,8 @@
     }
 
     public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
-        mRemoteDevice = remoteDevice;
+        // TODO: Move from decorator to direct binder-mediated exceptions
+        mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
     }
 
     @Override
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
index e87f84c..c39488e 100644
--- a/core/java/android/net/BaseNetworkStateTracker.java
+++ b/core/java/android/net/BaseNetworkStateTracker.java
@@ -57,6 +57,10 @@
         mLinkCapabilities = new LinkCapabilities();
     }
 
+    protected BaseNetworkStateTracker() {
+        // By default, let the sub classes construct everything
+    }
+
     @Deprecated
     protected Handler getTargetHandler() {
         return mTarget;
@@ -73,30 +77,37 @@
     }
 
     @Override
-    public final void startMonitoring(Context context, Handler target) {
+    public void startMonitoring(Context context, Handler target) {
         mContext = Preconditions.checkNotNull(context);
         mTarget = Preconditions.checkNotNull(target);
         startMonitoringInternal();
     }
 
-    protected abstract void startMonitoringInternal();
+    protected void startMonitoringInternal() {
+
+    }
 
     @Override
-    public final NetworkInfo getNetworkInfo() {
+    public NetworkInfo getNetworkInfo() {
         return new NetworkInfo(mNetworkInfo);
     }
 
     @Override
-    public final LinkProperties getLinkProperties() {
+    public LinkProperties getLinkProperties() {
         return new LinkProperties(mLinkProperties);
     }
 
     @Override
-    public final LinkCapabilities getLinkCapabilities() {
+    public LinkCapabilities getLinkCapabilities() {
         return new LinkCapabilities(mLinkCapabilities);
     }
 
     @Override
+    public LinkInfo getLinkInfo() {
+        return null;
+    }
+
+    @Override
     public void captivePortalCheckComplete() {
         // not implemented
     }
@@ -176,4 +187,23 @@
     public void supplyMessenger(Messenger messenger) {
         // not supported on this network
     }
+
+    @Override
+    public String getNetworkInterfaceName() {
+        if (mLinkProperties != null) {
+            return mLinkProperties.getInterfaceName();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void startSampling(SamplingDataTracker.SamplingSnapshot s) {
+        // nothing to do
+    }
+
+    @Override
+    public void stopSampling(SamplingDataTracker.SamplingSnapshot s) {
+        // nothing to do
+    }
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1b418fa..f6a3a4a 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1442,4 +1442,43 @@
         }
         return null;
     }
+
+    /**
+     * get the information about a specific network link
+     * @hide
+     */
+    public LinkInfo getLinkInfo(int networkType) {
+        try {
+            LinkInfo li = mService.getLinkInfo(networkType);
+            return li;
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * get the information of currently active network link
+     * @hide
+     */
+    public LinkInfo getActiveLinkInfo() {
+        try {
+            LinkInfo li = mService.getActiveLinkInfo();
+            return li;
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * get the information of all network links
+     * @hide
+     */
+    public LinkInfo[] getAllLinkInfo() {
+        try {
+            LinkInfo[] li = mService.getAllLinkInfo();
+            return li;
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index ee738fd..51a1191 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -29,18 +29,14 @@
  *
  * {@hide}
  */
-public class DummyDataStateTracker implements NetworkStateTracker {
+public class DummyDataStateTracker extends BaseNetworkStateTracker {
 
     private static final String TAG = "DummyDataStateTracker";
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
-    private NetworkInfo mNetworkInfo;
     private boolean mTeardownRequested = false;
     private Handler mTarget;
-    private Context mContext;
-    private LinkProperties mLinkProperties;
-    private LinkCapabilities mLinkCapabilities;
     private boolean mPrivateDnsRouteSet = false;
     private boolean mDefaultRouteSet = false;
 
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 7999c66..501484c 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -27,6 +27,8 @@
 import android.os.ServiceManager;
 import android.util.Log;
 
+import com.android.server.net.BaseNetworkObserver;
+
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -36,7 +38,7 @@
  * ConnectivityService.
  * @hide
  */
-public class EthernetDataTracker implements NetworkStateTracker {
+public class EthernetDataTracker extends BaseNetworkStateTracker {
     private static final String NETWORKTYPE = "ETHERNET";
     private static final String TAG = "Ethernet";
 
@@ -46,15 +48,11 @@
     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
 
     private static boolean mLinkUp;
-    private LinkProperties mLinkProperties;
-    private LinkCapabilities mLinkCapabilities;
-    private NetworkInfo mNetworkInfo;
     private InterfaceObserver mInterfaceObserver;
     private String mHwAddr;
 
     /* For sending events to connectivity service handler */
     private Handler mCsHandler;
-    private Context mContext;
 
     private static EthernetDataTracker sInstance;
     private static String sIfaceMatch = "";
@@ -62,7 +60,7 @@
 
     private INetworkManagementService mNMService;
 
-    private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
+    private static class InterfaceObserver extends BaseNetworkObserver {
         private EthernetDataTracker mTracker;
 
         InterfaceObserver(EthernetDataTracker tracker) {
@@ -70,10 +68,12 @@
             mTracker = tracker;
         }
 
+        @Override
         public void interfaceStatusChanged(String iface, boolean up) {
             Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
         }
 
+        @Override
         public void interfaceLinkStateChanged(String iface, boolean up) {
             if (mIface.equals(iface)) {
                 Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
@@ -89,21 +89,15 @@
             }
         }
 
+        @Override
         public void interfaceAdded(String iface) {
             mTracker.interfaceAdded(iface);
         }
 
+        @Override
         public void interfaceRemoved(String iface) {
             mTracker.interfaceRemoved(iface);
         }
-
-        public void limitReached(String limitName, String iface) {
-            // Ignored.
-        }
-
-        public void interfaceClassDataActivityChanged(String label, boolean active) {
-            // Ignored.
-        }
     }
 
     private EthernetDataTracker() {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 992ec37..bf2dade 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.net.LinkInfo;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.NetworkQuotaInfo;
@@ -145,4 +146,11 @@
     String getMobileProvisioningUrl();
 
     String getMobileRedirectedProvisioningUrl();
+
+    LinkInfo getLinkInfo(int networkType);
+
+    LinkInfo getActiveLinkInfo();
+
+    LinkInfo[] getAllLinkInfo();
+
 }
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index 6f4dd5f..b76e4c2 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -53,6 +53,27 @@
      */
     void interfaceRemoved(String iface);
 
+
+    /**
+     * An interface address has been added or updated
+     *
+     * @param address The address.
+     * @param iface The interface.
+     * @param flags The address flags.
+     * @param scope The address scope.
+     */
+    void addressUpdated(String address, String iface, int flags, int scope);
+
+    /**
+     * An interface address has been removed
+     *
+     * @param address The address.
+     * @param iface The interface.
+     * @param flags The address flags.
+     * @param scope The address scope.
+     */
+    void addressRemoved(String address, String iface, int flags, int scope);
+
     /**
      * A networking quota limit has been reached. The quota might not
      * be specific to an interface.
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index f6a114c..a390add 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -32,27 +32,56 @@
     /**
      * IPv4 or IPv6 address.
      */
-    private final InetAddress address;
+    private InetAddress address;
 
     /**
      * Network prefix length
      */
-    private final int prefixLength;
+    private int prefixLength;
 
-    public LinkAddress(InetAddress address, int prefixLength) {
+    private void init(InetAddress address, int prefixLength) {
         if (address == null || prefixLength < 0 ||
                 ((address instanceof Inet4Address) && prefixLength > 32) ||
                 (prefixLength > 128)) {
             throw new IllegalArgumentException("Bad LinkAddress params " + address +
-                    prefixLength);
+                    "/" + prefixLength);
         }
         this.address = address;
         this.prefixLength = prefixLength;
     }
 
+    public LinkAddress(InetAddress address, int prefixLength) {
+        init(address, prefixLength);
+    }
+
     public LinkAddress(InterfaceAddress interfaceAddress) {
-        this.address = interfaceAddress.getAddress();
-        this.prefixLength = interfaceAddress.getNetworkPrefixLength();
+        init(interfaceAddress.getAddress(),
+             interfaceAddress.getNetworkPrefixLength());
+    }
+
+    /**
+     * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or
+     * "2001:db8::1/64".
+     * @param string The string to parse.
+     */
+    public LinkAddress(String address) {
+        InetAddress inetAddress = null;
+        int prefixLength = -1;
+        try {
+            String [] pieces = address.split("/", 2);
+            prefixLength = Integer.parseInt(pieces[1]);
+            inetAddress = InetAddress.parseNumericAddress(pieces[0]);
+        } catch (NullPointerException e) {            // Null string.
+        } catch (ArrayIndexOutOfBoundsException e) {  // No prefix length.
+        } catch (NumberFormatException e) {           // Non-numeric prefix.
+        } catch (IllegalArgumentException e) {        // Invalid IP address.
+        }
+
+        if (inetAddress == null || prefixLength == -1) {
+            throw new IllegalArgumentException("Bad LinkAddress params " + address);
+        }
+
+        init(inetAddress, prefixLength);
     }
 
     @Override
diff --git a/core/java/android/net/LinkInfo.aidl b/core/java/android/net/LinkInfo.aidl
new file mode 100644
index 0000000..716674b
--- /dev/null
+++ b/core/java/android/net/LinkInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.net;
+
+parcelable LinkInfo;
diff --git a/core/java/android/net/LinkInfo.java b/core/java/android/net/LinkInfo.java
new file mode 100644
index 0000000..98e8f35
--- /dev/null
+++ b/core/java/android/net/LinkInfo.java
@@ -0,0 +1,128 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ *  Class that represents useful attributes of generic network links
+ *  such as the upload/download throughput or packet error rate.
+ *  Generally speaking, you should be dealing with instances of
+ *  LinkInfo subclasses, such as {@link android.net.#WifiLinkInfo}
+ *  or {@link android.net.#MobileLinkInfo} which provide additional
+ *  information.
+ *  @hide
+ */
+public class LinkInfo implements Parcelable
+{
+    public static final int UNKNOWN = Integer.MAX_VALUE;
+
+    public static final int NORMALIZED_MIN_SIGNAL_STRENGTH = 0;
+
+    public static final int NORMALIZED_MAX_SIGNAL_STRENGTH = 99;
+
+    public static final int NORMALIZED_SIGNAL_STRENGTH_RANGE = NORMALIZED_MAX_SIGNAL_STRENGTH + 1;
+
+    /* Network type as defined by ConnectivityManager */
+    public int mNetworkType = ConnectivityManager.TYPE_NONE;
+
+    public int mNormalizedSignalStrength = UNKNOWN;
+
+    public int mPacketCount = UNKNOWN;
+    public int mPacketErrorCount = UNKNOWN;
+    public int mTheoreticalTxBandwidth = UNKNOWN;
+    public int mTheoreticalRxBandwidth = UNKNOWN;
+    public int mTheoreticalLatency = UNKNOWN;
+
+    /* Timestamp when last sample was made available */
+    public long mLastDataSampleTime = UNKNOWN;
+
+    /* Sample duration in millisecond */
+    public int mDataSampleDuration = UNKNOWN;
+
+    public LinkInfo() {
+
+    }
+
+    /**
+     * Implement the Parcelable interface
+     * @hide
+     */
+    public int describeContents() {
+        return 0;
+    }
+    /**
+     * Implement the Parcelable interface.
+     */
+
+    protected static final int OBJECT_TYPE_LINKINFO = 1;
+    protected static final int OBJECT_TYPE_WIFI_LINKINFO = 2;
+    protected static final int OBJECT_TYPE_MOBILE_LINKINFO = 3;
+
+    public void writeToParcel(Parcel dest, int flags) {
+        writeToParcel(dest, flags, OBJECT_TYPE_LINKINFO);
+    }
+
+    public void writeToParcel(Parcel dest, int flags, int objectType) {
+        dest.writeInt(objectType);
+        dest.writeInt(mNetworkType);
+        dest.writeInt(mNormalizedSignalStrength);
+        dest.writeInt(mPacketCount);
+        dest.writeInt(mPacketErrorCount);
+        dest.writeInt(mTheoreticalTxBandwidth);
+        dest.writeInt(mTheoreticalRxBandwidth);
+        dest.writeInt(mTheoreticalLatency);
+        dest.writeLong(mLastDataSampleTime);
+        dest.writeInt(mDataSampleDuration);
+    }
+
+    public static final Creator<LinkInfo> CREATOR =
+            new Creator<LinkInfo>() {
+                public LinkInfo createFromParcel(Parcel in) {
+                    int objectType = in.readInt();
+                    if (objectType == OBJECT_TYPE_LINKINFO) {
+                        LinkInfo li = new LinkInfo();
+                        li.initializeFromParcel(in);
+                        return li;
+                    } else if (objectType == OBJECT_TYPE_WIFI_LINKINFO) {
+                        return WifiLinkInfo.createFromParcelBody(in);
+                    } else if (objectType == OBJECT_TYPE_MOBILE_LINKINFO) {
+                        return MobileLinkInfo.createFromParcelBody(in);
+                    } else {
+                        return null;
+                    }
+                }
+
+                public LinkInfo[] newArray(int size) {
+                    return new LinkInfo[size];
+                }
+            };
+
+    protected void initializeFromParcel(Parcel in) {
+        mNetworkType = in.readInt();
+        mNormalizedSignalStrength = in.readInt();
+        mPacketCount = in.readInt();
+        mPacketErrorCount = in.readInt();
+        mTheoreticalTxBandwidth = in.readInt();
+        mTheoreticalRxBandwidth = in.readInt();
+        mTheoreticalLatency = in.readInt();
+        mLastDataSampleTime = in.readLong();
+        mDataSampleDuration = in.readInt();
+    }
+
+}
diff --git a/core/java/android/net/LinkProperties.aidl b/core/java/android/net/LinkProperties.aidl
index 9cd06d5..3cb9525 100644
--- a/core/java/android/net/LinkProperties.aidl
+++ b/core/java/android/net/LinkProperties.aidl
@@ -18,4 +18,3 @@
 package android.net;
 
 parcelable LinkProperties;
-
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 6ab810c..1f73c4a 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -23,6 +23,7 @@
 
 import java.net.InetAddress;
 import java.net.Inet4Address;
+import java.net.Inet6Address;
 
 import java.net.UnknownHostException;
 import java.util.ArrayList;
@@ -153,8 +154,28 @@
         return addresses;
     }
 
-    public void addLinkAddress(LinkAddress address) {
-        if (address != null) mLinkAddresses.add(address);
+    /**
+     * Adds a link address if it does not exist, or update it if it does.
+     * @param address The {@code LinkAddress} to add.
+     * @return true if the address was added, false if it already existed.
+     */
+    public boolean addLinkAddress(LinkAddress address) {
+        // TODO: when the LinkAddress has other attributes beyond the
+        // address and the prefix length, update them here.
+        if (address != null && !mLinkAddresses.contains(address)) {
+            mLinkAddresses.add(address);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Removes a link address.
+     * @param address The {@code LinkAddress} to remove.
+     * @return true if the address was removed, false if it did not exist.
+     */
+    public boolean removeLinkAddress(LinkAddress toRemove) {
+        return mLinkAddresses.remove(toRemove);
     }
 
     /**
@@ -245,11 +266,14 @@
      * of stacked links. If link is null, nothing changes.
      *
      * @param link The link to add.
+     * @return true if the link was stacked, false otherwise.
      */
-    public void addStackedLink(LinkProperties link) {
+    public boolean addStackedLink(LinkProperties link) {
         if (link != null && link.getInterfaceName() != null) {
             mStackedLinks.put(link.getInterfaceName(), link);
+            return true;
         }
+        return false;
     }
 
     /**
@@ -258,12 +282,15 @@
      * If there a stacked link with the same interfacename as link, it is
      * removed. Otherwise, nothing changes.
      *
-     * @param link The link to add.
+     * @param link The link to remove.
+     * @return true if the link was removed, false otherwise.
      */
-    public void removeStackedLink(LinkProperties link) {
+    public boolean removeStackedLink(LinkProperties link) {
         if (link != null && link.getInterfaceName() != null) {
-            mStackedLinks.remove(link.getInterfaceName());
+            LinkProperties removed = mStackedLinks.remove(link.getInterfaceName());
+            return removed != null;
         }
+        return false;
     }
 
     /**
@@ -340,6 +367,20 @@
     }
 
     /**
+     * Returns true if this link has an IPv6 address.
+     *
+     * @return {@code true} if there is an IPv6 address, {@code false} otherwise.
+     */
+    public boolean hasIPv6Address() {
+        for (LinkAddress address : mLinkAddresses) {
+          if (address.getAddress() instanceof Inet6Address) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
      * Compares this {@code LinkProperties} interface name against the target
      *
      * @param target LinkProperties to compare.
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index e4fd312..faa13b0 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -28,6 +28,8 @@
 import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Slog;
@@ -49,7 +51,7 @@
  *
  * {@hide}
  */
-public class MobileDataStateTracker implements NetworkStateTracker {
+public class MobileDataStateTracker extends BaseNetworkStateTracker {
 
     private static final String TAG = "MobileDataStateTracker";
     private static final boolean DBG = true;
@@ -59,12 +61,8 @@
     private ITelephony mPhoneService;
 
     private String mApnType;
-    private NetworkInfo mNetworkInfo;
     private boolean mTeardownRequested = false;
     private Handler mTarget;
-    private Context mContext;
-    private LinkProperties mLinkProperties;
-    private LinkCapabilities mLinkCapabilities;
     private boolean mPrivateDnsRouteSet = false;
     private boolean mDefaultRouteSet = false;
 
@@ -78,6 +76,10 @@
 
     private AtomicBoolean mIsCaptivePortal = new AtomicBoolean(false);
 
+    private SignalStrength mSignalStrength;
+
+    private SamplingDataTracker mSamplingDataTracker = new SamplingDataTracker();
+
     /**
      * Create a new MobileDataStateTracker
      * @param netType the ConnectivityManager network type
@@ -108,8 +110,19 @@
 
         mContext.registerReceiver(new MobileDataStateReceiver(), filter);
         mMobileDataState = PhoneConstants.DataState.DISCONNECTED;
+
+        TelephonyManager tm = (TelephonyManager)mContext.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
     }
 
+    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            mSignalStrength = signalStrength;
+        }
+    };
+
     static class MdstHandler extends Handler {
         private MobileDataStateTracker mMdst;
 
@@ -251,6 +264,30 @@
                             setDetailedState(DetailedState.CONNECTED, reason, apnName);
                             break;
                     }
+
+                    if (VDBG) {
+                        Slog.d(TAG, "TelephonyMgr.DataConnectionStateChanged");
+                        if (mNetworkInfo != null) {
+                            Slog.d(TAG, "NetworkInfo = " + mNetworkInfo.toString());
+                            Slog.d(TAG, "subType = " + String.valueOf(mNetworkInfo.getSubtype()));
+                            Slog.d(TAG, "subType = " + mNetworkInfo.getSubtypeName());
+                        }
+                        if (mLinkProperties != null) {
+                            Slog.d(TAG, "LinkProperties = " + mLinkProperties.toString());
+                        } else {
+                            Slog.d(TAG, "LinkProperties = " );
+                        }
+
+                        if (mLinkCapabilities != null) {
+                            Slog.d(TAG, "LinkCapabilities = " + mLinkCapabilities.toString());
+                        } else {
+                            Slog.d(TAG, "LinkCapabilities = " );
+                        }
+                    }
+
+
+                    /* lets not sample traffic data across state changes */
+                    mSamplingDataTracker.resetSamplingData();
                 } else {
                     // There was no state change. Check if LinkProperties has been updated.
                     if (TextUtils.equals(reason, PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) {
@@ -283,7 +320,7 @@
                 String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
                 if (DBG) {
                     log("Received " + intent.getAction() +
-                                " broadcast" + reason == null ? "" : "(" + reason + ")");
+                                " broadcast" + (reason == null ? "" : "(" + reason + ")"));
                 }
                 setDetailedState(DetailedState.FAILED, reason, apnName);
             } else {
@@ -557,7 +594,7 @@
         return writer.toString();
     }
 
-   /**
+    /**
      * Internal method supporting the ENABLE_MMS feature.
      * @param apnType the type of APN to be enabled or disabled (e.g., mms)
      * @param enable {@code true} to enable the specified APN type,
@@ -617,9 +654,11 @@
         }
     }
 
+
     /**
      * @see android.net.NetworkStateTracker#getLinkProperties()
      */
+    @Override
     public LinkProperties getLinkProperties() {
         return new LinkProperties(mLinkProperties);
     }
@@ -627,6 +666,7 @@
     /**
      * @see android.net.NetworkStateTracker#getLinkCapabilities()
      */
+    @Override
     public LinkCapabilities getLinkCapabilities() {
         return new LinkCapabilities(mLinkCapabilities);
     }
@@ -648,4 +688,152 @@
     static private void sloge(String s) {
         Slog.e(TAG, s);
     }
+
+    @Override
+    public LinkInfo getLinkInfo() {
+        if (mNetworkInfo == null || mNetworkInfo.getType() == ConnectivityManager.TYPE_NONE) {
+            // no data available yet; just return
+            return null;
+        }
+
+        MobileLinkInfo li = new MobileLinkInfo();
+
+        li.mNetworkType = mNetworkInfo.getType();
+
+        mSamplingDataTracker.setCommonLinkInfoFields(li);
+
+        if (mNetworkInfo.getSubtype() != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+            li.mMobileNetworkType = mNetworkInfo.getSubtype();
+
+            NetworkDataEntry entry = getNetworkDataEntry(mNetworkInfo.getSubtype());
+            if (entry != null) {
+                li.mTheoreticalRxBandwidth = entry.downloadBandwidth;
+                li.mTheoreticalRxBandwidth = entry.uploadBandwidth;
+                li.mTheoreticalLatency = entry.latency;
+            }
+
+            if (mSignalStrength != null) {
+                li.mNormalizedSignalStrength = getNormalizedSignalStrength(
+                        li.mMobileNetworkType, mSignalStrength);
+            }
+        }
+
+        SignalStrength ss = mSignalStrength;
+        if (ss != null) {
+
+            li.mRssi = ss.getGsmSignalStrength();
+            li.mGsmErrorRate = ss.getGsmBitErrorRate();
+            li.mCdmaDbm = ss.getCdmaDbm();
+            li.mCdmaEcio = ss.getCdmaEcio();
+            li.mEvdoDbm = ss.getEvdoDbm();
+            li.mEvdoEcio = ss.getEvdoEcio();
+            li.mEvdoSnr = ss.getEvdoSnr();
+            li.mLteSignalStrength = ss.getLteSignalStrength();
+            li.mLteRsrp = ss.getLteRsrp();
+            li.mLteRsrq = ss.getLteRsrq();
+            li.mLteRssnr = ss.getLteRssnr();
+            li.mLteCqi = ss.getLteCqi();
+        }
+
+        if (VDBG) {
+            Slog.d(TAG, "Returning LinkInfo with"
+                    + " MobileNetworkType = " + String.valueOf(li.mMobileNetworkType)
+                    + " Theoretical Rx BW = " + String.valueOf(li.mTheoreticalRxBandwidth)
+                    + " gsm Signal Strength = " + String.valueOf(li.mRssi)
+                    + " cdma Signal Strength = " + String.valueOf(li.mCdmaDbm)
+                    + " evdo Signal Strength = " + String.valueOf(li.mEvdoDbm)
+                    + " Lte Signal Strength = " + String.valueOf(li.mLteSignalStrength));
+        }
+
+        return li;
+    }
+
+    static class NetworkDataEntry {
+        public int networkType;
+        public int downloadBandwidth;               // in kbps
+        public int uploadBandwidth;                 // in kbps
+        public int latency;                         // in millisecond
+
+        NetworkDataEntry(int i1, int i2, int i3, int i4) {
+            networkType = i1;
+            downloadBandwidth = i2;
+            uploadBandwidth = i3;
+            latency = i4;
+        }
+    }
+
+    private static NetworkDataEntry [] mTheoreticalBWTable = new NetworkDataEntry[] {
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EDGE,     237,   118, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_GPRS,      48,    40, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_UMTS,     384,    64, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSDPA,  14400,    -1, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSUPA,  14400,  5760, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSPA,   14400,  5760, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSPAP,  21000,  5760, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_CDMA,      -1,    -1, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_1xRTT,     -1,    -1, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_0,  2468,   153, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_A,  3072,  1800, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_B, 14700,  1800, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_IDEN,      -1,    -1, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_LTE,   100000, 50000, -1),
+            new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EHRPD,     -1,    -1, -1),
+    };
+
+    private static NetworkDataEntry getNetworkDataEntry(int networkType) {
+        for (NetworkDataEntry entry : mTheoreticalBWTable) {
+            if (entry.networkType == networkType) {
+                return entry;
+            }
+        }
+
+        Slog.e(TAG, "Could not find Theoretical BW entry for " + String.valueOf(networkType));
+        return null;
+    }
+
+    private static int getNormalizedSignalStrength(int networkType, SignalStrength ss) {
+
+        int level;
+
+        switch(networkType) {
+            case TelephonyManager.NETWORK_TYPE_EDGE:
+            case TelephonyManager.NETWORK_TYPE_GPRS:
+            case TelephonyManager.NETWORK_TYPE_UMTS:
+            case TelephonyManager.NETWORK_TYPE_HSDPA:
+            case TelephonyManager.NETWORK_TYPE_HSUPA:
+            case TelephonyManager.NETWORK_TYPE_HSPA:
+            case TelephonyManager.NETWORK_TYPE_HSPAP:
+                level = ss.getGsmLevel();
+                break;
+            case TelephonyManager.NETWORK_TYPE_CDMA:
+            case TelephonyManager.NETWORK_TYPE_1xRTT:
+                level = ss.getCdmaLevel();
+                break;
+            case TelephonyManager.NETWORK_TYPE_EVDO_0:
+            case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            case TelephonyManager.NETWORK_TYPE_EVDO_B:
+                level = ss.getEvdoLevel();
+                break;
+            case TelephonyManager.NETWORK_TYPE_LTE:
+                level = ss.getLteLevel();
+                break;
+            case TelephonyManager.NETWORK_TYPE_IDEN:
+            case TelephonyManager.NETWORK_TYPE_EHRPD:
+            default:
+                return LinkInfo.UNKNOWN;
+        }
+
+        return (level * LinkInfo.NORMALIZED_SIGNAL_STRENGTH_RANGE) /
+                SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+    }
+
+    @Override
+    public void startSampling(SamplingDataTracker.SamplingSnapshot s) {
+        mSamplingDataTracker.startSampling(s);
+    }
+
+    @Override
+    public void stopSampling(SamplingDataTracker.SamplingSnapshot s) {
+        mSamplingDataTracker.stopSampling(s);
+    }
 }
diff --git a/core/java/android/net/MobileLinkInfo.java b/core/java/android/net/MobileLinkInfo.java
new file mode 100644
index 0000000..2d18275
--- /dev/null
+++ b/core/java/android/net/MobileLinkInfo.java
@@ -0,0 +1,89 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.net.LinkInfo;
+
+/**
+ *  Class that represents useful attributes of mobile network links
+ *  such as the upload/download throughput or error rate etc.
+ *  @hide
+ */
+public final class MobileLinkInfo extends LinkInfo
+{
+    // Represents TelephonyManager.NetworkType
+    public int mMobileNetworkType = UNKNOWN;
+    public int mRssi = UNKNOWN;
+    public int mGsmErrorRate = UNKNOWN;
+    public int mCdmaDbm = UNKNOWN;
+    public int mCdmaEcio = UNKNOWN;
+    public int mEvdoDbm = UNKNOWN;
+    public int mEvdoEcio = UNKNOWN;
+    public int mEvdoSnr = UNKNOWN;
+    public int mLteSignalStrength = UNKNOWN;
+    public int mLteRsrp = UNKNOWN;
+    public int mLteRsrq = UNKNOWN;
+    public int mLteRssnr = UNKNOWN;
+    public int mLteCqi = UNKNOWN;
+
+    /**
+     * Implement the Parcelable interface.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags, OBJECT_TYPE_MOBILE_LINKINFO);
+
+        dest.writeInt(mMobileNetworkType);
+        dest.writeInt(mRssi);
+        dest.writeInt(mGsmErrorRate);
+        dest.writeInt(mCdmaDbm);
+        dest.writeInt(mCdmaEcio);
+        dest.writeInt(mEvdoDbm);
+        dest.writeInt(mEvdoEcio);
+        dest.writeInt(mEvdoSnr);
+        dest.writeInt(mLteSignalStrength);
+        dest.writeInt(mLteRsrp);
+        dest.writeInt(mLteRsrq);
+        dest.writeInt(mLteRssnr);
+        dest.writeInt(mLteCqi);
+    }
+
+    /* Un-parceling helper */
+    public static MobileLinkInfo createFromParcelBody(Parcel in) {
+
+        MobileLinkInfo li = new MobileLinkInfo();
+
+        li.initializeFromParcel(in);
+
+        li.mMobileNetworkType = in.readInt();
+        li.mRssi = in.readInt();
+        li.mGsmErrorRate = in.readInt();
+        li.mCdmaDbm = in.readInt();
+        li.mCdmaEcio = in.readInt();
+        li.mEvdoDbm = in.readInt();
+        li.mEvdoEcio = in.readInt();
+        li.mEvdoSnr = in.readInt();
+        li.mLteSignalStrength = in.readInt();
+        li.mLteRsrp = in.readInt();
+        li.mLteRsrq = in.readInt();
+        li.mLteRssnr = in.readInt();
+        li.mLteCqi = in.readInt();
+
+        return li;
+    }
+}
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 9ed7533..a3d7b14 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -83,7 +83,6 @@
      */
     public static final int EVENT_NETWORK_DISCONNECTED = BASE_NETWORK_STATE_TRACKER + 5;
 
-
     /**
      * -------------------------------------------------------------
      * Control Interface
@@ -120,6 +119,12 @@
     public LinkCapabilities getLinkCapabilities();
 
     /**
+     * Get interesting information about this network link
+     * @return a copy of link information, null if not available
+     */
+    public LinkInfo getLinkInfo();
+
+    /**
      * Return the system properties name associated with the tcp buffer sizes
      * for this network.
      */
@@ -234,4 +239,20 @@
      * the underlying network specific code.
      */
     public void supplyMessenger(Messenger messenger);
+
+    /*
+     * Network interface name that we'll lookup for sampling data
+     */
+    public String getNetworkInterfaceName();
+
+    /*
+     * Save the starting sample
+     */
+    public void startSampling(SamplingDataTracker.SamplingSnapshot s);
+
+    /*
+     * Save the ending sample
+     */
+    public void stopSampling(SamplingDataTracker.SamplingSnapshot s);
+
 }
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java
index d3ce2e5..b674324 100644
--- a/core/java/android/net/PacProxySelector.java
+++ b/core/java/android/net/PacProxySelector.java
@@ -1,3 +1,18 @@
+/*
+ * 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.net;
 
@@ -25,19 +40,25 @@
     private static final String TAG = "PacProxySelector";
     public static final String PROXY_SERVICE = "com.android.net.IProxyService";
     private IProxyService mProxyService;
+    private final List<Proxy> mDefaultList;
 
     public PacProxySelector() {
         mProxyService = IProxyService.Stub.asInterface(
                 ServiceManager.getService(PROXY_SERVICE));
         if (mProxyService == null) {
             // Added because of b10267814 where mako is restarting.
-            Log.e(TAG, "PackManager: no proxy service");
+            Log.e(TAG, "PacManager: no proxy service");
         }
+        mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY);
     }
 
     @Override
     public List<Proxy> select(URI uri) {
         if (mProxyService == null) {
+            mProxyService = IProxyService.Stub.asInterface(
+                    ServiceManager.getService(PROXY_SERVICE));
+        }
+        if (mProxyService == null) {
             Log.e(TAG, "select: no proxy service return NO_PROXY");
             return Lists.newArrayList(java.net.Proxy.NO_PROXY);
         }
@@ -53,6 +74,9 @@
         } catch (RemoteException e) {
             e.printStackTrace();
         }
+        if (response == null) {
+            return mDefaultList;
+        }
 
         return parseResponse(response);
     }
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 5b38f57..c3e1438 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -48,7 +48,6 @@
     private static final String TAG = "Proxy";
 
     private static final ProxySelector sDefaultProxySelector;
-    private static PacProxySelector sPacProxySelector;
 
     /**
      * Used to notify an app that's caching the default connection proxy
@@ -352,11 +351,8 @@
             System.clearProperty("http.nonProxyHosts");
             System.clearProperty("https.nonProxyHosts");
         }
-        if ((pacFileUrl != null) && !TextUtils.isEmpty(pacFileUrl)) {
-            if (sPacProxySelector == null) {
-                sPacProxySelector = new PacProxySelector();
-            }
-            ProxySelector.setDefault(sPacProxySelector);
+        if (!TextUtils.isEmpty(pacFileUrl)) {
+            ProxySelector.setDefault(new PacProxySelector());
         } else {
             ProxySelector.setDefault(sDefaultProxySelector);
         }
diff --git a/core/java/android/net/SamplingDataTracker.java b/core/java/android/net/SamplingDataTracker.java
new file mode 100644
index 0000000..b5dc140
--- /dev/null
+++ b/core/java/android/net/SamplingDataTracker.java
@@ -0,0 +1,295 @@
+/*
+ * 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.net;
+
+
+import android.os.SystemClock;
+import android.util.Slog;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @hide
+ */
+public class SamplingDataTracker
+{
+    private static final boolean DBG = false;
+    private static final String  TAG = "SamplingDataTracker";
+
+    public static class SamplingSnapshot
+    {
+        public int  mTxByteCount;
+        public int  mRxByteCount;
+        public int  mTxPacketCount;
+        public int  mRxPacketCount;
+        public int  mTxPacketErrorCount;
+        public int  mRxPacketErrorCount;
+        public long mTimestamp;
+    }
+
+    public static void getSamplingSnapshots(Map<String, SamplingSnapshot> mapIfaceToSample) {
+
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader("/proc/net/dev"));
+
+            // Skip over the line bearing column titles (there are 2 lines)
+            String line;
+            reader.readLine();
+            reader.readLine();
+
+            while ((line = reader.readLine()) != null) {
+
+                // remove leading whitespace
+                line = line.trim();
+
+                String[] tokens = line.split("[ ]+");
+                if (tokens.length < 17) {
+                    continue;
+                }
+
+                /* column format is
+                 * Interface  (Recv)bytes packets errs drop fifo frame compressed multicast \
+                 *            (Transmit)bytes packets errs drop fifo colls carrier compress
+                */
+
+                String currentIface = tokens[0].split(":")[0];
+                if (DBG) Slog.d(TAG, "Found data for interface " + currentIface);
+                if (mapIfaceToSample.containsKey(currentIface)) {
+
+                    SamplingSnapshot ss = new SamplingSnapshot();
+
+                    ss.mTxByteCount        = Integer.parseInt(tokens[1]);
+                    ss.mTxPacketCount      = Integer.parseInt(tokens[2]);
+                    ss.mTxPacketErrorCount = Integer.parseInt(tokens[3]);
+                    ss.mRxByteCount        = Integer.parseInt(tokens[9]);
+                    ss.mRxPacketCount      = Integer.parseInt(tokens[10]);
+                    ss.mRxPacketErrorCount = Integer.parseInt(tokens[11]);
+
+                    ss.mTimestamp          = SystemClock.elapsedRealtime();
+
+                    if (DBG) {
+                        Slog.d(TAG, "Interface = " + currentIface);
+                        Slog.d(TAG, "ByteCount = " + String.valueOf(ss.mTxByteCount));
+                        Slog.d(TAG, "TxPacketCount = " + String.valueOf(ss.mTxPacketCount));
+                        Slog.d(TAG, "TxPacketErrorCount = "
+                                + String.valueOf(ss.mTxPacketErrorCount));
+                        Slog.d(TAG, "RxByteCount = " + String.valueOf(ss.mRxByteCount));
+                        Slog.d(TAG, "RxPacketCount = " + String.valueOf(ss.mRxPacketCount));
+                        Slog.d(TAG, "RxPacketErrorCount = "
+                                + String.valueOf(ss.mRxPacketErrorCount));
+                        Slog.d(TAG, "Timestamp = " + String.valueOf(ss.mTimestamp));
+                        Slog.d(TAG, "---------------------------");
+                    }
+
+                    mapIfaceToSample.put(currentIface, ss);
+                }
+            }
+
+            if (DBG) {
+                Iterator it = mapIfaceToSample.entrySet().iterator();
+                while (it.hasNext()) {
+                    Map.Entry kvpair = (Map.Entry)it.next();
+                    if (kvpair.getValue() == null) {
+                        Slog.d(TAG, "could not find snapshot for interface " + kvpair.getKey());
+                    }
+                }
+            }
+        } catch(FileNotFoundException e) {
+            Slog.e(TAG, "could not find /proc/net/dev");
+        } catch (IOException e) {
+            Slog.e(TAG, "could not read /proc/net/dev");
+        } finally {
+            try {
+                if (reader != null) {
+                    reader.close();
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "could not close /proc/net/dev");
+            }
+        }
+    }
+
+    // Snapshots from previous sampling interval
+    private SamplingSnapshot mBeginningSample;
+    private SamplingSnapshot mEndingSample;
+
+    // Starting snapshot of current interval
+    private SamplingSnapshot mLastSample;
+
+    // Protects sampling data from concurrent access
+    public final Object mSamplingDataLock = new Object();
+
+    // We need long enough time for a good sample
+    private final int MINIMUM_SAMPLING_INTERVAL = 15 * 1000;
+
+    // statistics is useless unless we have enough data
+    private final int MINIMUM_SAMPLED_PACKETS   = 30;
+
+    public void startSampling(SamplingSnapshot s) {
+        synchronized(mSamplingDataLock) {
+            mLastSample = s;
+        }
+    }
+
+    public void stopSampling(SamplingSnapshot s) {
+        synchronized(mSamplingDataLock) {
+            if (mLastSample != null) {
+                if (s.mTimestamp - mLastSample.mTimestamp > MINIMUM_SAMPLING_INTERVAL
+                        && getSampledPacketCount(mLastSample, s) > MINIMUM_SAMPLED_PACKETS) {
+                    mBeginningSample = mLastSample;
+                    mEndingSample = s;
+                    mLastSample = null;
+                } else {
+                    if (DBG) Slog.d(TAG, "Throwing current sample away because it is too small");
+                }
+            }
+        }
+    }
+
+    public void resetSamplingData() {
+        if (DBG) Slog.d(TAG, "Resetting sampled network data");
+        synchronized(mSamplingDataLock) {
+
+            // We could just take another sample here and treat it as an
+            // 'ending sample' effectively shortening sampling interval, but that
+            // requires extra work (specifically, reading the sample needs to be
+            // done asynchronously)
+
+            mLastSample = null;
+        }
+    }
+
+    public int getSampledTxByteCount() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return mEndingSample.mTxByteCount - mBeginningSample.mTxByteCount;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public int getSampledTxPacketCount() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return mEndingSample.mTxPacketCount - mBeginningSample.mTxPacketCount;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public int getSampledTxPacketErrorCount() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return mEndingSample.mTxPacketErrorCount - mBeginningSample.mTxPacketErrorCount;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public int getSampledRxByteCount() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return mEndingSample.mRxByteCount - mBeginningSample.mRxByteCount;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public int getSampledRxPacketCount() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return mEndingSample.mRxPacketCount - mBeginningSample.mRxPacketCount;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public int getSampledPacketCount() {
+        return getSampledPacketCount(mBeginningSample, mEndingSample);
+    }
+
+    public int getSampledPacketCount(SamplingSnapshot begin, SamplingSnapshot end) {
+        if (begin != null && end != null) {
+            int rxPacketCount = end.mRxPacketCount - begin.mRxPacketCount;
+            int txPacketCount = end.mTxPacketCount - begin.mTxPacketCount;
+            return rxPacketCount + txPacketCount;
+        } else {
+            return LinkInfo.UNKNOWN;
+        }
+    }
+
+    public int getSampledPacketErrorCount() {
+        if (mBeginningSample != null && mEndingSample != null) {
+            int rxPacketErrorCount = getSampledRxPacketErrorCount();
+            int txPacketErrorCount = getSampledTxPacketErrorCount();
+            return rxPacketErrorCount + txPacketErrorCount;
+        } else {
+            return LinkInfo.UNKNOWN;
+        }
+    }
+
+    public int getSampledRxPacketErrorCount() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return mEndingSample.mRxPacketErrorCount - mBeginningSample.mRxPacketErrorCount;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public long getSampleTimestamp() {
+        synchronized(mSamplingDataLock) {
+            if (mEndingSample != null) {
+                return mEndingSample.mTimestamp;
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public int getSampleDuration() {
+        synchronized(mSamplingDataLock) {
+            if (mBeginningSample != null && mEndingSample != null) {
+                return (int) (mEndingSample.mTimestamp - mBeginningSample.mTimestamp);
+            } else {
+                return LinkInfo.UNKNOWN;
+            }
+        }
+    }
+
+    public void setCommonLinkInfoFields(LinkInfo li) {
+        synchronized(mSamplingDataLock) {
+            li.mLastDataSampleTime = getSampleTimestamp();
+            li.mDataSampleDuration = getSampleDuration();
+            li.mPacketCount = getSampledPacketCount();
+            li.mPacketErrorCount = getSampledPacketErrorCount();
+        }
+    }
+}
+
diff --git a/core/java/android/net/WifiLinkInfo.java b/core/java/android/net/WifiLinkInfo.java
new file mode 100644
index 0000000..f3b0032
--- /dev/null
+++ b/core/java/android/net/WifiLinkInfo.java
@@ -0,0 +1,75 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.net.LinkInfo;
+
+/**
+ *  Class that represents useful attributes of wifi network links
+ *  such as the upload/download throughput or error rate etc.
+ *  @hide
+ */
+public final class WifiLinkInfo extends LinkInfo
+{
+    /**
+     * Type enumerations for Wifi Network
+     */
+
+    /* Indicates Wifi network type such as b/g etc*/
+    public int  mType = UNKNOWN;
+
+    public String mBssid;
+
+    /* Rssi found by scans */
+    public int  mRssi = UNKNOWN;
+
+    /* packet statistics */
+    public int  mTxGood = UNKNOWN;
+    public int  mTxBad = UNKNOWN;
+
+    /**
+     * Implement the Parcelable interface.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags, OBJECT_TYPE_WIFI_LINKINFO);
+
+        dest.writeInt(mType);
+        dest.writeInt(mRssi);
+        dest.writeInt(mTxGood);
+        dest.writeInt(mTxBad);
+
+        dest.writeString(mBssid);
+    }
+
+    /* Un-parceling helper */
+    public static WifiLinkInfo createFromParcelBody(Parcel in) {
+        WifiLinkInfo li = new WifiLinkInfo();
+
+        li.initializeFromParcel(in);
+
+        li.mType =  in.readInt();
+        li.mRssi =  in.readInt();
+        li.mTxGood =  in.readInt();
+        li.mTxBad =  in.readInt();
+
+        li.mBssid =  in.readString();
+
+        return li;
+    }
+}
diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/core/java/android/nfc/cardemulation/HostApduService.java
index 6d091c1..cdc4adb 100644
--- a/core/java/android/nfc/cardemulation/HostApduService.java
+++ b/core/java/android/nfc/cardemulation/HostApduService.java
@@ -4,11 +4,13 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Service;
 import android.content.Intent;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
+import android.os.Parcel;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -98,6 +100,12 @@
     public static final int MSG_DEACTIVATED = 2;
 
     /**
+     *
+     * @hide
+     */
+    public static final int MSG_UNHANDLED = 3;
+
+    /**
      * @hide
      */
     public static final String KEY_DATA = "data";
@@ -105,6 +113,8 @@
     /**
      * Messenger interface to NfcService for sending responses.
      * Only accessed on main thread by the message handler.
+     *
+     * @hide
      */
     Messenger mNfcService = null;
 
@@ -133,6 +143,7 @@
                         Bundle responseBundle = new Bundle();
                         responseBundle.putByteArray(KEY_DATA, responseApdu);
                         responseMsg.setData(responseBundle);
+                        responseMsg.replyTo = mMessenger;
                         try {
                             mNfcService.send(responseMsg);
                         } catch (RemoteException e) {
@@ -150,6 +161,7 @@
                     return;
                 }
                 try {
+                    msg.replyTo = mMessenger;
                     mNfcService.send(msg);
                 } catch (RemoteException e) {
                     Log.e(TAG, "RemoteException calling into NfcService.");
@@ -160,6 +172,18 @@
                 mNfcService = null;
                 onDeactivated(msg.arg1);
                 break;
+            case MSG_UNHANDLED:
+                if (mNfcService == null) {
+                    Log.e(TAG, "notifyUnhandled not sent; service was deactivated.");
+                    return;
+                }
+                try {
+                    msg.replyTo = mMessenger;
+                    mNfcService.send(msg);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException calling into NfcService.");
+                }
+                break;
             default:
                 super.handleMessage(msg);
             }
@@ -190,6 +214,38 @@
     }
 
     /**
+     * Calling this method allows the service to tell the OS
+     * that it won't be able to complete this transaction -
+     * for example, because it requires data connectivity
+     * that is not present at that moment.
+     *
+     * The OS may use this indication to give the user a list
+     * of alternative applications that can handle the last
+     * AID that was selected. If the user would select an
+     * application from the list, that action by itself
+     * will not cause the default to be changed; the selected
+     * application will be invoked for the next tap only.
+     *
+     * If there are no other applications that can handle
+     * this transaction, the OS will show an error dialog
+     * indicating your service could not complete the
+     * transaction.
+     *
+     * <p>Note: this method may be called anywhere between
+     *    the first {@link #processCommandApdu(byte[], int)}
+     *    call and a {@link #onDeactivated(int)} call.
+     */
+    public final void notifyUnhandled() {
+        Message unhandledMsg = Message.obtain(null, MSG_UNHANDLED);
+        try {
+            mMessenger.send(unhandledMsg);
+        } catch (RemoteException e) {
+            Log.e("TAG", "Local messenger has died.");
+        }
+    }
+
+
+    /**
      * <p>This method will be called when a command APDU has been received
      * from a remote device. A response APDU can be provided directly
      * by returning a byte-array in this method. Note that in general
@@ -205,6 +261,33 @@
      * If you cannot return a response APDU immediately, return null
      * and use the {@link #sendResponseApdu(byte[])} method later.
      *
+     * @param commandApdu The APDU that received from the remote device
+     * @param extras A bundle containing extra data. May be null.
+     * @return a byte-array containing the response APDU, or null if no
+     *         response APDU can be sent at this point.
+     */
+    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
+        // TODO make this abstract
+        return processCommandApdu(commandApdu, 0);
+    }
+
+    /**
+     * <p>This method will be called when a command APDU has been received
+     * from a remote device. A response APDU can be provided directly
+     * by returning a byte-array in this method. Note that in general
+     * response APDUs must be sent as quickly as possible, given the fact
+     * that the user is likely holding his device over an NFC reader
+     * when this method is called.
+     *
+     * <p class="note">If there are multiple services that have registered for the same
+     * AIDs in their meta-data entry, you will only get called if the user has
+     * explicitly selected your service, either as a default or just for the next tap.
+     *
+     * <p class="note">This method is running on the main thread of your application.
+     * If you cannot return a response APDU immediately, return null
+     * and use the {@link #sendResponseApdu(byte[])} method later.
+     *
+     * @deprecated use {@link #processCommandApdu(byte[], Bundle)}
      * @param commandApdu
      * @param flags
      * @return a byte-array containing the response APDU, or null if no
diff --git a/core/java/android/preference/OnDependencyChangeListener.java b/core/java/android/preference/OnDependencyChangeListener.java
deleted file mode 100644
index ce25e34..0000000
--- a/core/java/android/preference/OnDependencyChangeListener.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2007 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.preference;
-
-/**
- * Interface definition for a callback to be invoked when this
- * {@link Preference} changes with respect to enabling/disabling
- * dependents.
- */
-interface OnDependencyChangeListener {
-    /**
-     * Called when this preference has changed in a way that dependents should
-     * care to change their state.
-     * 
-     * @param disablesDependent Whether the dependent should be disabled.
-     */
-    void onDependencyChanged(Preference dependency, boolean disablesDependent);
-}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 6c02965..37a8102 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -77,7 +77,7 @@
  * @attr ref android.R.styleable#Preference_defaultValue
  * @attr ref android.R.styleable#Preference_shouldDisableView
  */
-public class Preference implements Comparable<Preference>, OnDependencyChangeListener { 
+public class Preference implements Comparable<Preference> {
     /**
      * Specify for {@link #setOrder(int)} if a specific order is not required.
      */
@@ -115,6 +115,7 @@
     private String mDependencyKey;
     private Object mDefaultValue;
     private boolean mDependencyMet = true;
+    private boolean mParentDependencyMet = true;
     
     /**
      * @see #setShouldDisableView(boolean)
@@ -123,7 +124,7 @@
     
     private int mLayoutResId = com.android.internal.R.layout.preference;
     private int mWidgetLayoutResId;
-    private boolean mHasSpecifiedLayout = false;
+    private boolean mCanRecycleLayout = true;
     
     private OnPreferenceChangeInternalListener mListener;
     
@@ -274,9 +275,10 @@
         }
         a.recycle();
 
-        if (!getClass().getName().startsWith("android.preference")) {
-            // For subclasses not in this package, assume the worst and don't cache views
-            mHasSpecifiedLayout = true;
+        if (!getClass().getName().startsWith("android.preference")
+                && !getClass().getName().startsWith("com.android")) {
+            // For non-framework subclasses, assume the worst and don't cache views.
+            mCanRecycleLayout = false;
         }
     }
     
@@ -398,7 +400,7 @@
     public void setLayoutResource(int layoutResId) {
         if (layoutResId != mLayoutResId) {
             // Layout changed
-            mHasSpecifiedLayout = true;
+            mCanRecycleLayout = false;
         }
 
         mLayoutResId = layoutResId;
@@ -414,7 +416,7 @@
     }
     
     /**
-     * Sets The layout for the controllable widget portion of this Preference. This
+     * Sets the layout for the controllable widget portion of this Preference. This
      * is inflated into the main layout. For example, a {@link CheckBoxPreference}
      * would specify a custom layout (consisting of just the CheckBox) here,
      * instead of creating its own main layout.
@@ -426,7 +428,7 @@
     public void setWidgetLayoutResource(int widgetLayoutResId) {
         if (widgetLayoutResId != mWidgetLayoutResId) {
             // Layout changed
-            mHasSpecifiedLayout = true;
+            mCanRecycleLayout = false;
         }
         mWidgetLayoutResId = widgetLayoutResId;
     }
@@ -733,7 +735,7 @@
      * @return True if this Preference is enabled, false otherwise.
      */
     public boolean isEnabled() {
-        return mEnabled && mDependencyMet;
+        return mEnabled && mDependencyMet && mParentDependencyMet;
     }
 
     /**
@@ -1259,7 +1261,24 @@
             notifyChanged();
         }
     }
-    
+
+    /**
+     * Called when the implicit parent dependency changes.
+     *
+     * @param parent The Preference that this Preference depends on.
+     * @param disableChild Set true to disable this Preference.
+     */
+    public void onParentChanged(Preference parent, boolean disableChild) {
+        if (mParentDependencyMet == disableChild) {
+            mParentDependencyMet = !disableChild;
+
+            // Enabled state can change dependent preferences' states, so notify
+            notifyDependencyChange(shouldDisableDependents());
+
+            notifyChanged();
+        }
+    }
+
     /**
      * Checks whether this preference's dependents should currently be
      * disabled.
@@ -1641,8 +1660,8 @@
         return mPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);
     }
     
-    boolean hasSpecifiedLayout() {
-        return mHasSpecifiedLayout;
+    boolean canRecycleLayout() {
+        return mCanRecycleLayout;
     }
     
     @Override
diff --git a/core/java/android/preference/PreferenceCategory.java b/core/java/android/preference/PreferenceCategory.java
index d8af3248..229a96a 100644
--- a/core/java/android/preference/PreferenceCategory.java
+++ b/core/java/android/preference/PreferenceCategory.java
@@ -62,4 +62,8 @@
         return false;
     }
     
+    @Override
+    public boolean shouldDisableDependents() {
+        return !super.isEnabled();
+    }
 }
diff --git a/core/java/android/preference/PreferenceGroup.java b/core/java/android/preference/PreferenceGroup.java
index f33a6be..a5e05ba 100644
--- a/core/java/android/preference/PreferenceGroup.java
+++ b/core/java/android/preference/PreferenceGroup.java
@@ -290,13 +290,14 @@
     }
 
     @Override
-    public void setEnabled(boolean enabled) {
-        super.setEnabled(enabled);
-        
-        // Dispatch to all contained preferences
+    public void notifyDependencyChange(boolean disableDependents) {
+        super.notifyDependencyChange(disableDependents);
+
+        // Child preferences have an implicit dependency on their containing
+        // group. Dispatch dependency change to all contained preferences.
         final int preferenceCount = getPreferenceCount();
         for (int i = 0; i < preferenceCount; i++) {
-            getPreference(i).setEnabled(enabled);
+            getPreference(i).onParentChanged(this, disableDependents);
         }
     }
     
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index a908ecd..23d0a19 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -153,7 +153,7 @@
             
             preferences.add(preference);
             
-            if (!mHasReturnedViewTypeCount && !preference.hasSpecifiedLayout()) {
+            if (!mHasReturnedViewTypeCount && preference.canRecycleLayout()) {
                 addPreferenceClassName(preference);
             }
             
@@ -255,7 +255,7 @@
         }
         
         final Preference preference = this.getItem(position);
-        if (preference.hasSpecifiedLayout()) {
+        if (!preference.canRecycleLayout()) {
             return IGNORE_ITEM_VIEW_TYPE;
         }
 
diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl
index 8178180..5c8a22a 100644
--- a/core/java/android/print/IPrintSpooler.aidl
+++ b/core/java/android/print/IPrintSpooler.aidl
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.os.ParcelFileDescriptor;
+import android.print.PrinterId;
 import android.print.IPrintDocumentAdapter;
 import android.print.IPrintClient;
 import android.print.IPrintSpoolerClient;
@@ -40,10 +41,15 @@
     void createPrintJob(String printJobName, in IPrintClient client,
             in IPrintDocumentAdapter printAdapter, in PrintAttributes attributes,
             IPrintSpoolerCallbacks callback, int appId, int sequence);
-    void setPrintJobState(int printJobId, int status, CharSequence error,
+    void setPrintJobState(int printJobId, int status, String error,
             IPrintSpoolerCallbacks callback, int sequence);
     void setPrintJobTag(int printJobId, String tag, IPrintSpoolerCallbacks callback,
             int sequence);
     void writePrintJobData(in ParcelFileDescriptor fd, int printJobId);
     void setClient(IPrintSpoolerClient client);
+
+    // Printer discovery APIs
+    void onPrintersAdded(in List<PrinterInfo> printers);
+    void onPrintersRemoved(in List<PrinterId> printerIds);
+    void onPrintersUpdated(in List<PrinterInfo> printerIds);
 }
diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl
index 8db2169..da60120 100644
--- a/core/java/android/print/IPrintSpoolerClient.aidl
+++ b/core/java/android/print/IPrintSpoolerClient.aidl
@@ -17,7 +17,6 @@
 package android.print;
 
 import android.content.ComponentName;
-import android.print.IPrinterDiscoverySessionObserver;
 import android.print.PrinterId;
 import android.print.PrintJobInfo;
 
@@ -28,8 +27,14 @@
  * @hide
  */
 oneway interface IPrintSpoolerClient {
-    void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
     void onPrintJobQueued(in PrintJobInfo printJob);
     void onAllPrintJobsForServiceHandled(in ComponentName printService);
     void onAllPrintJobsHandled();
+
+    // Printer discovery APIs
+    void createPrinterDiscoverySession();
+    void startPrinterDiscovery(in List<PrinterId> priorityList);
+    void stopPrinterDiscovery();
+    void requestPrinterUpdate(in PrinterId printerId);
+    void destroyPrinterDiscoverySession();
 }
diff --git a/core/java/android/print/IPrinterDiscoverySessionController.aidl b/core/java/android/print/IPrinterDiscoverySessionController.aidl
deleted file mode 100644
index 13116ef..0000000
--- a/core/java/android/print/IPrinterDiscoverySessionController.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.print;
-
-import android.print.PrinterId;
-
-/**
-* Interface for the controlling part of a printer discovery session.
- *
- * @hide
- */
-oneway interface IPrinterDiscoverySessionController {
-    void open(in List<PrinterId> priorityList);
-    void requestPrinterUpdate(in PrinterId printerId);
-    void close();
-}
diff --git a/core/java/android/print/IPrinterDiscoverySessionObserver.aidl b/core/java/android/print/IPrinterDiscoverySessionObserver.aidl
deleted file mode 100644
index a78924c..0000000
--- a/core/java/android/print/IPrinterDiscoverySessionObserver.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.print;
-
-import android.print.IPrinterDiscoverySessionController;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
-
-/**
- * Interface for the observing part of a printer discovery session.
- *
- * @hide
- */
-oneway interface IPrinterDiscoverySessionObserver {
-    void setController(IPrinterDiscoverySessionController controller);
-    void onPrintersAdded(in List<PrinterInfo> printers);
-    void onPrintersRemoved(in List<PrinterId> printerIds);
-    void onPrintersUpdated(in List<PrinterInfo> printerIds);
-}
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 2fb4751..602f3c1 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -104,7 +104,7 @@
     private int mId;
 
     /** The human readable print job label. */
-    private CharSequence mLabel;
+    private String mLabel;
 
     /** The unique id of the printer. */
     private PrinterId mPrinterId;
@@ -128,7 +128,7 @@
     private int mCopies;
 
     /** Failure reason if this job failed. */
-    private CharSequence mFailureReason;
+    private String mFailureReason;
 
     /** The pages to print */
     private PageRange[] mPageRanges;
@@ -163,7 +163,7 @@
 
     private PrintJobInfo(Parcel parcel) {
         mId = parcel.readInt();
-        mLabel = parcel.readCharSequence();
+        mLabel = parcel.readString();
         mPrinterId = parcel.readParcelable(null);
         mPrinterName = parcel.readString();
         mState = parcel.readInt();
@@ -171,9 +171,7 @@
         mUserId = parcel.readInt();
         mTag = parcel.readString();
         mCopies = parcel.readInt();
-        if (parcel.readInt() == 1) {
-            mFailureReason = parcel.readCharSequence();
-        }
+        mFailureReason = parcel.readString();
         if (parcel.readInt() == 1) {
             Parcelable[] parcelables = parcel.readParcelableArray(null);
             mPageRanges = new PageRange[parcelables.length];
@@ -214,7 +212,7 @@
      *
      * @return The label.
      */
-    public CharSequence getLabel() {
+    public String getLabel() {
         return mLabel;
     }
 
@@ -225,7 +223,7 @@
      *
      * @hide
      */
-    public void setLabel(CharSequence label) {
+    public void setLabel(String label) {
         mLabel = label;
     }
 
@@ -385,7 +383,7 @@
      *
      * @hide
      */
-    public CharSequence getFailureReason() {
+    public String getFailureReason() {
         return mFailureReason;
     }
 
@@ -396,7 +394,7 @@
      *
      * @hide
      */
-    public void setFailureReason(CharSequence failureReason) {
+    public void setFailureReason(String failureReason) {
         mFailureReason = failureReason;
     }
 
@@ -470,7 +468,7 @@
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mId);
-        parcel.writeCharSequence(mLabel);
+        parcel.writeString(mLabel);
         parcel.writeParcelable(mPrinterId, flags);
         parcel.writeString(mPrinterName);
         parcel.writeInt(mState);
@@ -478,12 +476,7 @@
         parcel.writeInt(mUserId);
         parcel.writeString(mTag);
         parcel.writeInt(mCopies);
-        if (mFailureReason != null) {
-            parcel.writeInt(1);
-            parcel.writeCharSequence(mFailureReason);
-        } else {
-            parcel.writeInt(0);
-        }
+        parcel.writeString(mFailureReason);
         if (mPageRanges != null) {
             parcel.writeInt(1);
             parcel.writeParcelableArray(mPageRanges, flags);
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 636b9d4..531dcb2 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -374,14 +374,14 @@
 
             @Override
             public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
+                if (info == null) {
+                    throw new NullPointerException("document info cannot be null");
+                }
                 final ILayoutResultCallback callback;
                 synchronized (mLock) {
                     callback = mCallback;
                     clearLocked();
                 }
-                if (info == null) {
-                    throw new IllegalArgumentException("info cannot be null");
-                }
                 if (callback != null) {
                     try {
                         callback.onLayoutFinished(info, changed, mSequence);
diff --git a/core/java/android/print/PrinterInfo.java b/core/java/android/print/PrinterInfo.java
index ac782a8..6f567a6 100644
--- a/core/java/android/print/PrinterInfo.java
+++ b/core/java/android/print/PrinterInfo.java
@@ -229,10 +229,11 @@
         /**
          * Constructor.
          *
-         * @param prototype Prototype from which to start building.
+         * @param other Other info from which to start building.
          */
-        public Builder(PrinterInfo prototype) {
-            mPrototype = prototype;
+        public Builder(PrinterInfo other) {
+            mPrototype = new PrinterInfo();
+            mPrototype.copyFrom(other);
         }
 
         /**
diff --git a/core/java/android/print/pdf/PdfDocument.java b/core/java/android/print/pdf/PdfDocument.java
index cfeb975..dbd7dd1 100644
--- a/core/java/android/print/pdf/PdfDocument.java
+++ b/core/java/android/print/pdf/PdfDocument.java
@@ -324,7 +324,7 @@
             /**
              * Creates a new builder with the mandatory page info attributes.
              *
-             * @param pageSize The page size in pixels.
+             * @param pageSize The page size in points, <strong>not</strong> dips.
              * @param pageNumber The page number.
              * @param density The page density in DPI.
              */
diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl
index 16b7a26..2cee1d8 100644
--- a/core/java/android/printservice/IPrintService.aidl
+++ b/core/java/android/printservice/IPrintService.aidl
@@ -16,7 +16,7 @@
 
 package android.printservice;
 
-import android.print.IPrinterDiscoverySessionObserver;
+import android.print.PrinterId;
 import android.print.PrintJobInfo;
 import android.printservice.IPrintServiceClient;
 
@@ -29,5 +29,10 @@
     void setClient(IPrintServiceClient client);
     void requestCancelPrintJob(in PrintJobInfo printJobInfo);
     void onPrintJobQueued(in PrintJobInfo printJobInfo);
-    void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
+
+    void createPrinterDiscoverySession();
+    void startPrinterDiscovery(in List<PrinterId> priorityList);
+    void stopPrinterDiscovery();
+    void requestPrinterUpdate(in PrinterId printerId);
+    void destroyPrinterDiscoverySession();
 }
diff --git a/core/java/android/printservice/IPrintServiceClient.aidl b/core/java/android/printservice/IPrintServiceClient.aidl
index f00b37c4..1e33fc0 100644
--- a/core/java/android/printservice/IPrintServiceClient.aidl
+++ b/core/java/android/printservice/IPrintServiceClient.aidl
@@ -29,7 +29,11 @@
 interface IPrintServiceClient {
     List<PrintJobInfo> getPrintJobInfos();
     PrintJobInfo getPrintJobInfo(int printJobId);
-    boolean setPrintJobState(int printJobId, int state, CharSequence error);
+    boolean setPrintJobState(int printJobId, int state, String error);
     boolean setPrintJobTag(int printJobId, String tag);
     oneway void writePrintJobData(in ParcelFileDescriptor fd, int printJobId);
+
+    void onPrintersAdded(in List<PrinterInfo> printers);
+    void onPrintersRemoved(in List<PrinterId> printerIds);
+    void onPrintersUpdated(in List<PrinterInfo> printers);
 }
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index 5f9a730..d2fbef2 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -24,6 +24,10 @@
  * This class represents a print job from the perspective of a print
  * service. It provides APIs for observing the print job state and
  * performing operations on the print job.
+ * <p>
+ * <strong>Note: </strong> All methods of this class must be executed on the main
+ * application thread.
+ * </p>
  */
 public final class PrintJob {
 
@@ -48,6 +52,7 @@
      * @return The id.
      */
     public int getId() {
+        PrintService.throwIfNotCalledOnMainThread();
         return mCachedInfo.getId();
     }
 
@@ -62,6 +67,7 @@
      * @return The print job info.
      */
     public PrintJobInfo getInfo() {
+        PrintService.throwIfNotCalledOnMainThread();
         if (isInImmutableState()) {
             return mCachedInfo;
         }
@@ -83,6 +89,7 @@
      * @return The document.
      */
     public PrintDocument getDocument() {
+        PrintService.throwIfNotCalledOnMainThread();
         return mDocument;
     }
 
@@ -96,6 +103,7 @@
      * @see #cancel()
      */
     public boolean isQueued() {
+        PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_QUEUED;
     }
 
@@ -110,6 +118,7 @@
      * @see #fail(CharSequence)
      */
     public boolean isStarted() {
+        PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_STARTED;
     }
 
@@ -122,6 +131,7 @@
      * @see #complete()
      */
     public boolean isCompleted() {
+        PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_COMPLETED;
     }
 
@@ -134,6 +144,7 @@
      * @see #fail(CharSequence)
      */
     public boolean isFailed() {
+        PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_FAILED;
     }
 
@@ -146,6 +157,7 @@
      * @see #cancel()
      */
     public boolean isCancelled() {
+        PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_FAILED;
     }
 
@@ -158,6 +170,7 @@
      * @see #isQueued()
      */
     public boolean start() {
+        PrintService.throwIfNotCalledOnMainThread();
         if (isQueued()) {
             return setState(PrintJobInfo.STATE_STARTED, null);
         }
@@ -173,6 +186,7 @@
      * @see #isStarted()
      */
     public boolean complete() {
+        PrintService.throwIfNotCalledOnMainThread();
         if (isStarted()) {
             return setState(PrintJobInfo.STATE_COMPLETED, null);
         }
@@ -191,7 +205,8 @@
      * @see #isQueued()
      * @see #isStarted()
      */
-    public boolean fail(CharSequence error) {
+    public boolean fail(String error) {
+        PrintService.throwIfNotCalledOnMainThread();
         if (isQueued() || isStarted()) {
             return setState(PrintJobInfo.STATE_FAILED, error);
         }
@@ -210,6 +225,7 @@
      * @see #isQueued()
      */
     public boolean cancel() {
+        PrintService.throwIfNotCalledOnMainThread();
         if (isQueued() || isStarted()) {
             return setState(PrintJobInfo.STATE_CANCELED, null);
         }
@@ -226,6 +242,7 @@
      * @return True if the tag was set, false otherwise.
      */
     public boolean setTag(String tag) {
+        PrintService.throwIfNotCalledOnMainThread();
         if (isInImmutableState()) {
             return false;
         }
@@ -263,7 +280,7 @@
                 || state == PrintJobInfo.STATE_CANCELED;
     }
 
-    private boolean setState(int state, CharSequence error) {
+    private boolean setState(int state, String error) {
         try {
             if (mPrintServiceClient.setPrintJobState(mCachedInfo.getId(), state, error)) {
                 // Best effort - update the state of the cached info since
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 92bccd4..f6c0a9a 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -25,7 +25,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.print.IPrinterDiscoverySessionObserver;
 import android.print.PrintJobInfo;
 import android.print.PrinterId;
 import android.util.Log;
@@ -77,8 +76,8 @@
  * completion, the print job should be marked as completed by calling {@link
  * PrintJob#complete() PrintJob.complete()} after which {@link PrintJob#isCompleted()
  * PrintJob.isCompleted()} would return true. In case of a failure, the print job should
- * be marked as failed by calling {@link PrintJob#fail(CharSequence) PrintJob.fail(
- * CharSequence)} after which {@link PrintJob#isFailed() PrintJob.isFailed()} would
+ * be marked as failed by calling {@link PrintJob#fail(String) PrintJob.fail(
+ * String)} after which {@link PrintJob#isFailed() PrintJob.isFailed()} would
  * return true.
  * </p>
  * <p>
@@ -146,6 +145,11 @@
  * {@link #SERVICE_META_DATA} and <code>&lt;{@link android.R.styleable#PrintService
  * print-service}&gt;</code>.
  * </p>
+ * <p>
+ * <strong>Note: </strong> All callbacks in this class are executed on the main
+ * application thread. You should also invoke any method of this class on the main
+ * application thread.
+ * </p>
  */
 public abstract class PrintService extends Service {
 
@@ -175,14 +179,14 @@
      */
     public static final String SERVICE_META_DATA = "android.printservice";
 
-    private final Object mLock = new Object();
-
     private Handler mHandler;
 
     private IPrintServiceClient mClient;
 
     private int mLastSessionId = -1;
 
+    private PrinterDiscoverySession mDiscoverySession;
+
     @Override
     protected final void attachBaseContext(Context base) {
         super.attachBaseContext(base);
@@ -245,21 +249,18 @@
      * @see PrintJob#isStarted() PrintJob.isStarted()
      */
     public final List<PrintJob> getActivePrintJobs() {
-        final IPrintServiceClient client;
-        synchronized (mLock) {
-            client = mClient;
-        }
-        if (client == null) {
+        throwIfNotCalledOnMainThread();
+        if (mClient == null) {
             return Collections.emptyList();
         }
         try {
             List<PrintJob> printJobs = null;
-            List<PrintJobInfo> printJobInfos = client.getPrintJobInfos();
+            List<PrintJobInfo> printJobInfos = mClient.getPrintJobInfos();
             if (printJobInfos != null) {
                 final int printJobInfoCount = printJobInfos.size();
                 printJobs = new ArrayList<PrintJob>(printJobInfoCount);
                 for (int i = 0; i < printJobInfoCount; i++) {
-                    printJobs.add(new PrintJob(printJobInfos.get(i), client));
+                    printJobs.add(new PrintJob(printJobInfos.get(i), mClient));
                 }
             }
             if (printJobs != null) {
@@ -278,23 +279,50 @@
      * @return Global printer id.
      */
     public final PrinterId generatePrinterId(String localId) {
+        throwIfNotCalledOnMainThread();
         return new PrinterId(new ComponentName(getPackageName(),
                 getClass().getName()), localId);
     }
 
+    static void throwIfNotCalledOnMainThread() {
+        if (!Looper.getMainLooper().isCurrentThread()) {
+            throw new IllegalAccessError("must be called from the main thread");
+        }
+    }
+
     @Override
     public final IBinder onBind(Intent intent) {
         return new IPrintService.Stub() {
             @Override
-            public void setClient(IPrintServiceClient client) {
-                mHandler.obtainMessage(ServiceHandler.MSG_SET_CLEINT, client)
-                        .sendToTarget();
+            public void createPrinterDiscoverySession() {
+                mHandler.sendEmptyMessage(ServiceHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION);
             }
 
             @Override
-            public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
-                mHandler.obtainMessage(ServiceHandler.MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION,
-                        observer).sendToTarget();
+            public void destroyPrinterDiscoverySession() {
+                mHandler.sendEmptyMessage(ServiceHandler.MSG_DESTROY_PRINTER_DISCOVERY_SESSION);
+            }
+
+            public void startPrinterDiscovery(List<PrinterId> priorityList) {
+                mHandler.obtainMessage(ServiceHandler.MSG_START_PRINTER_DISCOVERY,
+                        priorityList).sendToTarget();
+            }
+
+            @Override
+            public void stopPrinterDiscovery() {
+                mHandler.sendEmptyMessage(ServiceHandler.MSG_STOP_PRINTER_DISCOVERY);
+            }
+
+            @Override
+            public void requestPrinterUpdate(PrinterId printerId) {
+                mHandler.obtainMessage(ServiceHandler.MSG_REQUEST_PRINTER_UPDATE,
+                        printerId).sendToTarget();
+            }
+
+            @Override
+            public void setClient(IPrintServiceClient client) {
+                mHandler.obtainMessage(ServiceHandler.MSG_SET_CLEINT, client)
+                        .sendToTarget();
             }
 
             @Override
@@ -312,33 +340,62 @@
     }
 
     private final class ServiceHandler extends Handler {
-        public static final int MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION = 1;
-        public static final int MSG_ON_PRINTJOB_QUEUED = 2;
-        public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 3;
-        public static final int MSG_SET_CLEINT = 4;
+        public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1;
+        public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
+        public static final int MSG_START_PRINTER_DISCOVERY = 3;
+        public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
+        public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
+        public static final int MSG_ON_PRINTJOB_QUEUED = 6;
+        public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 7;
+        public static final int MSG_SET_CLEINT = 8;
 
         public ServiceHandler(Looper looper) {
             super(looper, null, true);
         }
 
         @Override
+        @SuppressWarnings("unchecked")
         public void handleMessage(Message message) {
             final int action = message.what;
             switch (action) {
-                case MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION: {
-                    IPrinterDiscoverySessionObserver observer =
-                            (IPrinterDiscoverySessionObserver) message.obj;
+                case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
                     PrinterDiscoverySession session = onCreatePrinterDiscoverySession();
                     if (session == null) {
                         throw new NullPointerException("session cannot be null");
                     }
-                    synchronized (mLock) {
-                        if (session.getId() == mLastSessionId) {
-                            throw new IllegalStateException("cannot reuse sessions");
-                        }
-                        mLastSessionId = session.getId();
+                    if (session.getId() == mLastSessionId) {
+                        throw new IllegalStateException("cannot reuse session instances");
                     }
-                    session.setObserver(observer);
+                    mDiscoverySession = session;
+                    mLastSessionId = session.getId();
+                    session.setObserver(mClient);
+                } break;
+
+                case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
+                    if (mDiscoverySession != null) {
+                        mDiscoverySession.destroy();
+                        mDiscoverySession = null;
+                    }
+                } break;
+
+                case MSG_START_PRINTER_DISCOVERY: {
+                    if (mDiscoverySession != null) {
+                        List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj;
+                        mDiscoverySession.startPrinterDiscovery(priorityList);
+                    }
+                } break;
+
+                case MSG_STOP_PRINTER_DISCOVERY: {
+                    if (mDiscoverySession != null) {
+                        mDiscoverySession.stopPrinterDiscovery();
+                    }
+                } break;
+
+                case MSG_REQUEST_PRINTER_UPDATE: {
+                    if (mDiscoverySession != null) {
+                        PrinterId printerId = (PrinterId) message.obj;
+                        mDiscoverySession.requestPrinterUpdate(printerId);
+                    }
                 } break;
 
                 case MSG_ON_REQUEST_CANCEL_PRINTJOB: {
@@ -352,15 +409,12 @@
                 } break;
 
                 case MSG_SET_CLEINT: {
-                    IPrintServiceClient client = (IPrintServiceClient) message.obj;
-                    synchronized (mLock) {
-                        mClient = client;
-                    }
-                    if (client != null) {
+                    mClient = (IPrintServiceClient) message.obj;
+                    if (mClient != null) {
                         onConnected();
                      } else {
                         onDisconnected();
-                    }
+                     }
                 } break;
 
                 default: {
diff --git a/core/java/android/printservice/PrinterDiscoverySession.java b/core/java/android/printservice/PrinterDiscoverySession.java
index 92dc0dd..8b959a6 100644
--- a/core/java/android/printservice/PrinterDiscoverySession.java
+++ b/core/java/android/printservice/PrinterDiscoverySession.java
@@ -16,18 +16,15 @@
 
 package android.printservice;
 
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
 import android.os.RemoteException;
-import android.print.IPrinterDiscoverySessionController;
-import android.print.IPrinterDiscoverySessionObserver;
+import android.print.PrinterCapabilitiesInfo;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
+import android.util.ArrayMap;
 import android.util.Log;
 
-import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -36,67 +33,75 @@
  * for adding discovered printers, removing already added printers that
  * disappeared, and updating already added printers.
  * <p>
- * The opening of the session is announced by a call to {@link
- * PrinterDiscoverySession#onOpen(List)} at which point you should start printer
- * discovery. The closing of the session is announced by a call to {@link
- * PrinterDiscoverySession#onClose()} at which point you should stop printer
- * discovery. Discovered printers are added by invoking {@link
- * PrinterDiscoverySession#addPrinters(List)}. Added printers that disappeared
- * are removed by invoking {@link PrinterDiscoverySession#removePrinters(List)}.
- * Added printers whose properties or capabilities changed are updated through
- * a call to {@link PrinterDiscoverySession#updatePrinters(List)}.
+ * During the lifetime of this session you may be asked to start and stop
+ * performing printer discovery multiple times. You will receive a call to {@link
+ * PrinterDiscoverySession#onStartPrinterDiscovery(List)} to start printer
+ * discovery and a call to {@link PrinterDiscoverySession#onStopPrinterDiscovery()}
+ * to stop printer discovery. When the system is no longer interested in printers
+ * discovered by this session you will receive a call to {@link #onDestroy()} at
+ * which point the system will no longer call into the session and all the session
+ * methods will do nothing.
+ * </p>
+ * <p>
+ * Discovered printers are added by invoking {@link
+ * PrinterDiscoverySession#addPrinters(List)}. Added printers that disappeared are
+ * removed by invoking {@link PrinterDiscoverySession#removePrinters(List)}. Added
+ * printers whose properties or capabilities changed are updated through a call to
+ * {@link PrinterDiscoverySession#updatePrinters(List)}. The printers added in this
+ * session can be acquired via {@link #getPrinters()} where the returned printers
+ * will be an up-to-date snapshot of the printers that you reported during the
+ * session. Printers are <strong>not</strong> persisted across sessions.
  * </p>
  * <p>
  * The system will make a call to
  * {@link PrinterDiscoverySession#onRequestPrinterUpdate(PrinterId)} if you
  * need to update a given printer. It is possible that you add a printer without
- * specifying its capabilities. This enables you to avoid querying all
- * discovered printers for their capabilities, rather querying the capabilities
- * of a printer only if necessary. For example, the system will require that you
- * update a printer if it gets selected by the user. If you did not report the
- * printer capabilities when adding it, you must do so after the system requests
- * a printer update. Otherwise, the printer will be ignored.
+ * specifying its capabilities. This enables you to avoid querying all discovered
+ * printers for their capabilities, rather querying the capabilities of a printer
+ * only if necessary. For example, the system will request that you update a printer
+ * if it gets selected by the user. If you did not report the printer capabilities
+ * when adding it, you must do so after the system requests a printer update.
+ * Otherwise, the printer will be ignored.
  * </p>
  * <p>
- * During printer discovery all printers that are known to your print service
- * have to be added. The system does not retain any printers from previous
- * sessions.
+ * <strong>Note: </strong> All callbacks in this class are executed on the main
+ * application thread. You also have to invoke any method of this class on the main
+ * application thread.
  * </p>
  */
 public abstract class PrinterDiscoverySession {
     private static final String LOG_TAG = "PrinterDiscoverySession";
 
+    private static final int MAX_ITEMS_PER_CALLBACK = 100;
+
     private static int sIdCounter = 0;
 
-    private final Object mLock = new Object();
-
-    private final Handler mHandler;
-
     private final int mId;
 
-    private IPrinterDiscoverySessionController mController;
+    private final ArrayMap<PrinterId, PrinterInfo> mPrinters =
+            new ArrayMap<PrinterId, PrinterInfo>();
 
-    private IPrinterDiscoverySessionObserver mObserver;
+    private ArrayMap<PrinterId, PrinterInfo> mLastSentPrinters;
+
+    private IPrintServiceClient mObserver;
+
+    private boolean mIsDestroyed;
+
+    private boolean mIsDiscoveryStarted;
 
     /**
      * Constructor.
-     *
-     * @param context A context instance.
      */
-    public PrinterDiscoverySession(Context context) {
+    public PrinterDiscoverySession() {
         mId = sIdCounter++;
-        mHandler = new SessionHandler(context.getMainLooper());
-        mController = new PrinterDiscoverySessionController(this);
     }
 
-    void setObserver(IPrinterDiscoverySessionObserver observer) {
-        synchronized (mLock) {
-            mObserver = observer;
-            try {
-                mObserver.setController(mController);
-            } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error setting session controller", re);
-            }
+    void setObserver(IPrintServiceClient observer) {
+        mObserver = observer;
+        // If some printers were added in the method that
+        // created the session, send them over.
+        if (!mPrinters.isEmpty()) {
+            sendAddedPrinters(mObserver, getPrinters());
         }
     }
 
@@ -105,131 +110,357 @@
     }
 
     /**
+     * Gets the printers reported in this session. For example, if you add two
+     * printers and remove one of them, the returned list will contain only
+     * the printer that was added but not removed.
+     * <p>
+     * <strong>Note: </strong> Calls to this method after the session is
+     * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+     * </p>
+     *
+     * @return The printers.
+     *
+     * @see #addPrinters(List)
+     * @see #removePrinters(List)
+     * @see #updatePrinters(List)
+     * @see #isDestroyed()
+     */
+    public final List<PrinterInfo> getPrinters() {
+        PrintService.throwIfNotCalledOnMainThread();
+        if (mIsDestroyed) {
+            return Collections.emptyList();
+        }
+        return new ArrayList<PrinterInfo>(mPrinters.values());
+    }
+
+    /**
      * Adds discovered printers. Adding an already added printer has no effect.
      * Removed printers can be added again. You can call this method multiple
-     * times during printer discovery.
+     * times during the life of this session. Duplicates will be ignored.
      * <p>
-     * <strong>Note: </strong> Calls to this method before the session is opened,
-     * i.e. before the {@link #onOpen(List)} call, and after the session is closed,
-     * i.e. after the call to {@link #onClose()}, will be ignored.
+     * <strong>Note: </strong> Calls to this method after the session is
+     * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
      * </p>
      *
      * @param printers The printers to add.
      *
      * @see #removePrinters(List)
      * @see #updatePrinters(List)
+     * @see #getPrinters()
+     * @see #isDestroyed()
      */
     public final void addPrinters(List<PrinterInfo> printers) {
-        final IPrinterDiscoverySessionObserver observer;
-        synchronized (mLock) {
-            observer = mObserver;
+        PrintService.throwIfNotCalledOnMainThread();
+
+        // If the session is destroyed - nothing do to.
+        if (mIsDestroyed) {
+            Log.w(LOG_TAG, "Not adding printers - session destroyed.");
+            return;
         }
-        if (observer != null) {
-            try {
-                observer.onPrintersAdded(printers);
-            } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error adding printers", re);
+
+        if (mIsDiscoveryStarted) {
+            // If during discovery, add the new printers and send them.
+            List<PrinterInfo> addedPrinters = new ArrayList<PrinterInfo>();
+            final int addedPrinterCount = printers.size();
+            for (int i = 0; i < addedPrinterCount; i++) {
+                PrinterInfo addedPrinter = printers.get(i);
+                if (mPrinters.get(addedPrinter.getId()) == null) {
+                    mPrinters.put(addedPrinter.getId(), addedPrinter);
+                    addedPrinters.add(addedPrinter);
+                }
+            }
+
+            // Send the added printers, if such.
+            if (!addedPrinters.isEmpty()) {
+                sendAddedPrinters(mObserver, addedPrinters);
             }
         } else {
-            Log.w(LOG_TAG, "Printer discovery session not open not adding printers.");
+            // Remember the last sent printers if needed.
+            if (mLastSentPrinters == null) {
+                mLastSentPrinters = new ArrayMap<PrinterId, PrinterInfo>(mPrinters);
+            }
+
+            // Update the printers.
+            final int addedPrinterCount = printers.size();
+            for (int i = 0; i < addedPrinterCount; i++) {
+                PrinterInfo addedPrinter = printers.get(i);
+                if (mPrinters.get(addedPrinter.getId()) == null) {
+                    mPrinters.put(addedPrinter.getId(), addedPrinter);
+                }
+            }
+        }
+    }
+
+    private static void sendAddedPrinters(IPrintServiceClient observer,
+        List<PrinterInfo> printers) {
+        try {
+            final int printerCount = printers.size();
+            if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
+                observer.onPrintersAdded(printers);
+            } else {
+                // Send the added printers in chunks avoiding the binder transaction limit.
+                final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
+                for (int i = 0; i < transactionCount; i++) {
+                    final int start = i * MAX_ITEMS_PER_CALLBACK;
+                    final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
+                    List<PrinterInfo> subPrinters = printers.subList(start, end);
+                    observer.onPrintersAdded(subPrinters);
+                }
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error sending added printers", re);
         }
     }
 
     /**
      * Removes added printers. Removing an already removed or never added
-     * printer has no effect. Removed printers can be added again. You
-     * can call this method multiple times during printer discovery.
+     * printer has no effect. Removed printers can be added again. You can
+     * call this method multiple times during the lifetime of this session.
      * <p>
-     * <strong>Note: </strong> Calls to this method before the session is opened,
-     * i.e. before the {@link #onOpen(List)} call, and after the session is closed,
-     * i.e. after the call to {@link #onClose()}, will be ignored.
+     * <strong>Note: </strong> Calls to this method after the session is
+     * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
      * </p>
      *
      * @param printerIds The ids of the removed printers.
      *
      * @see #addPrinters(List)
      * @see #updatePrinters(List)
+     * @see #getPrinters()
+     * @see #isDestroyed()
      */
     public final void removePrinters(List<PrinterId> printerIds) {
-        final IPrinterDiscoverySessionObserver observer;
-        synchronized (mLock) {
-            observer = mObserver;
+        PrintService.throwIfNotCalledOnMainThread();
+
+        // If the session is destroyed - nothing do to.
+        if (mIsDestroyed) {
+            Log.w(LOG_TAG, "Not removing printers - session destroyed.");
+            return;
         }
-        if (observer != null) {
-            try {
-                observer.onPrintersRemoved(printerIds);
-            } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error removing printers", re);
+
+        if (mIsDiscoveryStarted) {
+            // If during discovery, remove existing printers and send them.
+            List<PrinterId> removedPrinterIds = new ArrayList<PrinterId>();
+            final int removedPrinterIdCount = printerIds.size();
+            for (int i = 0; i < removedPrinterIdCount; i++) {
+                PrinterId removedPrinterId = printerIds.get(i);
+                if (mPrinters.remove(removedPrinterId) != null) {
+                    removedPrinterIds.add(removedPrinterId);
+                }
+            }
+
+            // Send the removed printers, if such.
+            if (!removedPrinterIds.isEmpty()) {
+                sendRemovedPrinters(mObserver, removedPrinterIds);
             }
         } else {
-            Log.w(LOG_TAG, "Printer discovery session not open not removing printers.");
+            // Remember the last sent printers if needed.
+            if (mLastSentPrinters == null) {
+                mLastSentPrinters = new ArrayMap<PrinterId, PrinterInfo>(mPrinters);
+            }
+
+            // Update the printers.
+            final int removedPrinterIdCount = printerIds.size();
+            for (int i = 0; i < removedPrinterIdCount; i++) {
+                PrinterId removedPrinterId = printerIds.get(i);
+                mPrinters.remove(removedPrinterId);
+            }
+        }
+    }
+
+    private static void sendRemovedPrinters(IPrintServiceClient observer,
+            List<PrinterId> printerIds) {
+        try {
+            final int printerIdCount = printerIds.size();
+            if (printerIdCount <= MAX_ITEMS_PER_CALLBACK) {
+                observer.onPrintersRemoved(printerIds);
+            } else {
+                final int transactionCount = (printerIdCount / MAX_ITEMS_PER_CALLBACK) + 1;
+                for (int i = 0; i < transactionCount; i++) {
+                    final int start = i * MAX_ITEMS_PER_CALLBACK;
+                    final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerIdCount);
+                    List<PrinterId> subPrinterIds = printerIds.subList(start, end);
+                    observer.onPrintersRemoved(subPrinterIds);
+                }
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error sending removed printers", re);
         }
     }
 
     /**
      * Updates added printers. Updating a printer that was not added or that
      * was removed has no effect. You can call this method multiple times
-     * during printer discovery.
+     * during the lifetime of this session.
      * <p>
-     * <strong>Note: </strong> Calls to this method before the session is opened,
-     * i.e. before the {@link #onOpen(List)} call, and after the session is closed,
-     * i.e. after the call to {@link #onClose()}, will be ignored.
+     * <strong>Note: </strong> Calls to this method after the session is
+     * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
      * </p>
      *
      * @param printers The printers to update.
      *
      * @see #addPrinters(List)
      * @see #removePrinters(List)
+     * @see #getPrinters()
+     * @see #isDestroyed()
      */
     public final void updatePrinters(List<PrinterInfo> printers) {
-        final IPrinterDiscoverySessionObserver observer;
-        synchronized (mLock) {
-            observer = mObserver;
+        PrintService.throwIfNotCalledOnMainThread();
+
+        // If the session is destroyed - nothing do to.
+        if (mIsDestroyed) {
+            Log.w(LOG_TAG, "Not updating printers - session destroyed.");
+            return;
         }
-        if (observer != null) {
-            try {
-                observer.onPrintersUpdated(printers);
-            } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error updating printers", re);
+
+        if (mIsDiscoveryStarted) {
+            // If during discovery, update existing printers and send them.
+            List<PrinterInfo> updatedPrinters = new ArrayList<PrinterInfo>();
+            final int updatedPrinterCount = printers.size();
+            for (int i = 0; i < updatedPrinterCount; i++) {
+                PrinterInfo updatedPrinter = printers.get(i);
+                PrinterInfo oldPrinter = mPrinters.get(updatedPrinter.getId());
+                if (oldPrinter != null && !oldPrinter.equals(updatedPrinter)) {
+                    mPrinters.put(updatedPrinter.getId(), updatedPrinter);
+                    updatedPrinters.add(updatedPrinter);
+                }
+            }
+
+            // Send the updated printers, if such.
+            if (!updatedPrinters.isEmpty()) {
+                sendUpdatedPrinters(mObserver, updatedPrinters);
             }
         } else {
-            Log.w(LOG_TAG, "Printer discovery session not open not updating printers.");
+            // Remember the last sent printers if needed.
+            if (mLastSentPrinters == null) {
+                mLastSentPrinters = new ArrayMap<PrinterId, PrinterInfo>(mPrinters);
+            }
+
+            // Update the printers.
+            final int updatedPrinterCount = printers.size();
+            for (int i = 0; i < updatedPrinterCount; i++) {
+                PrinterInfo updatedPrinter = printers.get(i);
+                PrinterInfo oldPrinter = mPrinters.get(updatedPrinter.getId());
+                if (oldPrinter != null && !oldPrinter.equals(updatedPrinter)) {
+                    mPrinters.put(updatedPrinter.getId(), updatedPrinter);
+                }
+            }
         }
     }
 
+    private static void sendUpdatedPrinters(IPrintServiceClient observer,
+            List<PrinterInfo> printers) {
+        try {
+            final int printerCount = printers.size();
+            if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
+                observer.onPrintersUpdated(printers);
+            } else {
+                final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
+                for (int i = 0; i < transactionCount; i++) {
+                    final int start = i * MAX_ITEMS_PER_CALLBACK;
+                    final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
+                    List<PrinterInfo> subPrinters = printers.subList(start, end);
+                    observer.onPrintersUpdated(subPrinters);
+                }
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error sending updated printers", re);
+        }
+    }
+
+    private void sendOutOfDiscoveryPeriodPrinterChanges() {
+        // Noting changed since the last discovery period - nothing to do.
+        if (mLastSentPrinters == null || mLastSentPrinters.isEmpty()) {
+            mLastSentPrinters = null;
+            return;
+        }
+
+        List<PrinterInfo> addedPrinters = null;
+        List<PrinterInfo> updatedPrinters = null;
+        List<PrinterId> removedPrinterIds = null;
+
+        // Determine the added and updated printers.
+        for (PrinterInfo printer : mPrinters.values()) {
+            PrinterInfo sentPrinter = mLastSentPrinters.get(printer.getId());
+            if (sentPrinter != null) {
+                if (!sentPrinter.equals(printer)) {
+                    if (updatedPrinters == null) {
+                        updatedPrinters = new ArrayList<PrinterInfo>();
+                    }
+                    updatedPrinters.add(printer);
+                }
+            } else {
+                if (addedPrinters == null) {
+                    addedPrinters = new ArrayList<PrinterInfo>();
+                }
+                addedPrinters.add(printer);
+            }
+        }
+
+        // Send the added printers, if such.
+        if (addedPrinters != null) {
+            sendAddedPrinters(mObserver, addedPrinters);
+        }
+
+        // Send the updated printers, if such.
+        if (updatedPrinters != null) {
+            sendUpdatedPrinters(mObserver, updatedPrinters);
+        }
+
+        // Determine the removed printers.
+        for (PrinterInfo sentPrinter : mLastSentPrinters.values()) {
+            if (!mPrinters.containsKey(sentPrinter.getId())) {
+                if (removedPrinterIds == null) {
+                    removedPrinterIds = new ArrayList<PrinterId>();
+                }
+                removedPrinterIds.add(sentPrinter.getId());
+            }
+        }
+
+        // Send the removed printers, if such.
+        if (removedPrinterIds != null) {
+            sendRemovedPrinters(mObserver, removedPrinterIds);
+        }
+
+        mLastSentPrinters = null;
+    }
+
     /**
-     * Callback notifying you that the session is open and you should start
-     * printer discovery. Discovered printers should be added via calling
-     * {@link #addPrinters(List)}. Added printers that disappeared should be
-     * removed via calling {@link #removePrinters(List)}. Added printers whose
-     * properties or capabilities changes should be updated via calling {@link
-     * #updatePrinters(List)}. When the session is closed you will receive a
-     * call to {@link #onClose()}.
+     * Callback asking you to start printer discovery. Discovered printers should be
+     * added via calling {@link #addPrinters(List)}. Added printers that disappeared
+     * should be removed via calling {@link #removePrinters(List)}. Added printers
+     * whose properties or capabilities changed should be updated via calling {@link
+     * #updatePrinters(List)}. You will receive a call to call to {@link
+     * #onStopPrinterDiscovery()} when you should stop printer discovery.
      * <p>
-     * During printer discovery all printers that are known to your print
-     * service have to be added. The system does not retain any printers from
-     * previous sessions.
+     * During the lifetime of this session all printers that are known to your print
+     * service have to be added. The system does not retain any printers across sessions.
+     * However, if you were asked to start and then stop performing printer discovery
+     * in this session, then a subsequent discovering should not re-discover already
+     * discovered printers.
      * </p>
      * <p>
-     * <strong>Note: </strong>You are also given a list of printers whose
-     * availability has to be checked first. For example, these printers could
-     * be the user's favorite ones, therefore they have to be verified first.
+     * <strong>Note: </strong>You are also given a list of printers whose availability
+     * has to be checked first. For example, these printers could be the user's favorite
+     * ones, therefore they have to be verified first.
      * </p>
      *
-     * @see #onClose()
+     * @param priorityList The list of printers to validate first. Never null.
+     *
+     * @see #onStopPrinterDiscovery()
      * @see #addPrinters(List)
      * @see #removePrinters(List)
      * @see #updatePrinters(List)
+     * @see #isPrinterDiscoveryStarted()
      */
-    public abstract void onOpen(List<PrinterId> priorityList);
+    public abstract void onStartPrinterDiscovery(List<PrinterId> priorityList);
 
     /**
-     * Callback notifying you that the session is closed and you should stop
-     * printer discovery. After the session is closed any call to the methods
-     * of this instance will be ignored. Once the session is closed
-     * it will never be opened again.
+     * Callback notifying you that you should stop printer discovery.
+     *
+     * @see #onStartPrinterDiscovery(List)
+     * @see #isPrinterDiscoveryStarted()
      */
-    public abstract void onClose();
+    public abstract void onStopPrinterDiscovery();
 
     /**
      * Requests that you update a printer. You are responsible for updating
@@ -255,77 +486,72 @@
      */
     public abstract void onRequestPrinterUpdate(PrinterId printerId);
 
-    void close() {
-        synchronized (mLock) {
-            mController = null;
+    /**
+     * Notifies you that the session is destroyed. After this callback is invoked
+     * any calls to the methods of this class will be ignored, {@link #isDestroyed()}
+     * will return true and you will also no longer receive callbacks.
+     *
+     * @see #isDestroyed()
+     */
+    public abstract void onDestroy();
+
+    /**
+     * Gets whether the session is destroyed.
+     *
+     * @return Whether the session is destroyed.
+     *
+     * @see #onDestroy()
+     */
+    public final boolean isDestroyed() {
+        PrintService.throwIfNotCalledOnMainThread();
+        return mIsDestroyed;
+    }
+
+    /**
+     * Gets whether printer discovery is started.
+     *
+     * @return Whether printer discovery is destroyed.
+     *
+     * @see #onStartPrinterDiscovery(List)
+     * @see #onStopPrinterDiscovery()
+     */
+    public final boolean isPrinterDiscoveryStarted() {
+        PrintService.throwIfNotCalledOnMainThread();
+        return mIsDiscoveryStarted;
+    }
+
+    void startPrinterDiscovery(List<PrinterId> priorityList) {
+        if (!mIsDestroyed) {
+            mIsDiscoveryStarted = true;
+            sendOutOfDiscoveryPeriodPrinterChanges();
+            if (priorityList == null) {
+                priorityList = Collections.emptyList();
+            }
+            onStartPrinterDiscovery(priorityList);
+        }
+    }
+
+    void stopPrinterDiscovery() {
+        if (!mIsDestroyed) {
+            mIsDiscoveryStarted = false;
+            onStopPrinterDiscovery();
+        }
+    }
+
+    void requestPrinterUpdate(PrinterId printerId) {
+        if (!mIsDestroyed) {
+            onRequestPrinterUpdate(printerId);
+        }
+    }
+
+    void destroy() {
+        if (!mIsDestroyed) {
+            mIsDestroyed = true;
+            mIsDiscoveryStarted = false;
+            mPrinters.clear();
+            mLastSentPrinters = null;
             mObserver = null;
+            onDestroy();
         }
     }
-
-    private final class SessionHandler extends Handler {
-        public static final int MSG_OPEN = 1;
-        public static final int MSG_CLOSE = 2;
-        public static final int MSG_REQUEST_PRINTER_UPDATE = 3;
-
-        public SessionHandler(Looper looper) {
-            super(looper, null, true);
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public void handleMessage(Message message) {
-            switch (message.what) {
-                case MSG_OPEN: {
-                    List<PrinterId> priorityList = (List<PrinterId>) message.obj;
-                    onOpen(priorityList);
-                } break;
-
-                case MSG_CLOSE: {
-                    onClose();
-                    close();
-                } break;
-
-                case MSG_REQUEST_PRINTER_UPDATE: {
-                    PrinterId printerId = (PrinterId) message.obj;
-                    onRequestPrinterUpdate(printerId);
-                } break;
-            }
-        }
-    }
-
-    private static final class PrinterDiscoverySessionController extends
-            IPrinterDiscoverySessionController.Stub {
-        private final WeakReference<PrinterDiscoverySession> mWeakSession;
-
-        public PrinterDiscoverySessionController(PrinterDiscoverySession session) {
-            mWeakSession = new WeakReference<PrinterDiscoverySession>(session);
-        }
-
-        @Override
-        public void open(List<PrinterId> priorityList) {
-            PrinterDiscoverySession session = mWeakSession.get();
-            if (session != null) {
-                session.mHandler.obtainMessage(SessionHandler.MSG_OPEN,
-                        priorityList).sendToTarget();
-            }
-        }
-
-        @Override
-        public void close() {
-            PrinterDiscoverySession session = mWeakSession.get();
-            if (session != null) {
-                session.mHandler.sendEmptyMessage(SessionHandler.MSG_CLOSE);
-            }
-        }
-
-        @Override
-        public void requestPrinterUpdate(PrinterId printerId) {
-            PrinterDiscoverySession session = mWeakSession.get();
-            if (session != null) {
-                session.mHandler.obtainMessage(
-                        SessionHandler.MSG_REQUEST_PRINTER_UPDATE,
-                        printerId).sendToTarget();
-            }
-        }
-    };
 }
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 3401cb1..f3267ee 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -21,12 +21,12 @@
 
 /**
  * The AlarmClock provider contains an Intent action and extras that can be used
- * to start an Activity to set a new alarm in an alarm clock application.
+ * to start an Activity to set a new alarm or timer in an alarm clock application.
  *
- * Applications that wish to receive the ACTION_SET_ALARM Intent should create
- * an activity to handle the Intent that requires the permission
+ * Applications that wish to receive the ACTION_SET_ALARM  and ACTION_SET_TIMER Intents
+ * should create an activity to handle the Intent that requires the permission
  * com.android.alarm.permission.SET_ALARM.  Applications that wish to create a
- * new alarm should use
+ * new alarm or timer should use
  * {@link android.content.Context#startActivity Context.startActivity()} so that
  * the user has the option of choosing which alarm clock application to use.
  */
@@ -34,49 +34,212 @@
     /**
      * Activity Action: Set an alarm.
      * <p>
-     * Input: Nothing.
-     * <p>
-     * Output: Nothing.
+     * Activates an existing alarm or creates a new one.
+     * </p><p>
+     * This action requests an alarm to be set for a given time of day. If an alarm already
+     * exists for this time, an implementation may use it rather than create a new one. If no time
+     * of day is specified, the implementation should start an activity that is capable of setting
+     * an alarm (SKIP_UI is ignored in this case). This action always enables the alarm.
+     * </p>
+     * <h3>Request parameters</h3>
+     * <ul>
+     * <li>{@link #EXTRA_HOUR} <em>(optional)</em>: The hour of the alarm being set.
+     * <li>{@link #EXTRA_MINUTES} <em>(optional)</em>: The minutes of the alarm being set.
+     * <li>{@link #EXTRA_DAYS} <em>(optional)</em>: Weekdays for repeating alarm.
+     * <li>{@link #EXTRA_MESSAGE} <em>(optional)</em>: A custom message for the alarm.
+     * <li>{@link #EXTRA_RINGTONE} <em>(optional)</em>: A ringtone to play with this alarm.
+     * <li>{@link #EXTRA_VIBRATE} <em>(optional)</em>: Whether or not to activate the device
+     * vibrator for this alarm.
+     * <li>{@link #EXTRA_SKIP_UI} <em>(optional)</em>: Whether or not to display an activity for
+     * setting this alarm.
+     * <li>{@link #EXTRA_DELETE_AFTER_USE} <em>(optional)</em>: Whether or not to delete this
+     * alarm after it is dismissed.
+     * </ul>
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
 
     /**
-     * Activity Extra: Provide a custom message for the alarm.
+     * Activity Action: Set a timer.
      * <p>
-     * This can be passed as an extra field in the Intent created with
-     * ACTION_SET_ALARM.
+     * Activates an existing timer or creates a new one.
+     * </p><p>
+     * This action requests a timer to be started for a specific {@link #EXTRA_LENGTH length} of
+     * time. If a timer already exists for this {@link #EXTRA_LENGTH length}, an implementation may
+     * use it rather than create a new one. If no {@link #EXTRA_LENGTH length} is specified, the
+     * implementation should start an activity that is capable of setting a timer
+     * ({@link #EXTRA_SKIP_UI} is ignored in this case).
+     * </p><p>
+     * An existing timer should only be used if it matches the provided extras and is not currently
+     * in use.
+     * </p>
+     *
+     * <h3>Request parameters</h3>
+     * <ul>
+     * <li>{@link #EXTRA_LENGTH} <em>(optional)</em>: The length of the timer being set.
+     * <li>{@link #EXTRA_MESSAGE} <em>(optional)</em>: A custom message for the timer.
+     * <li>{@link #EXTRA_SKIP_UI} <em>(optional)</em>: Whether or not to display an activity for
+     * setting this timer.
+     * <li>{@link #EXTRA_DELETE_AFTER_USE} <em>(optional)</em>: Whether or not to delete this
+     * timer after it is dismissed.
+     * </ul>
      */
-    public static final String EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
 
     /**
-     * Activity Extra: The hour of the alarm being set.
+     * Bundle extra: Weekdays for repeating alarm.
      * <p>
-     * This value can be passed as an extra field to the Intent created with
-     * ACTION_SET_ALARM.  If it is not provided, the behavior is undefined and
-     * is up to the application.  The value is an integer and ranges from 0 to
-     * 23.
+     * Used by {@link #ACTION_SET_ALARM}.
+     * </p><p>
+     * The value is an {@code ArrayList<Integer>}. Each item can be:
+     * </p>
+     * <ul>
+     * <li> {@link java.util.Calendar#SUNDAY},
+     * <li> {@link java.util.Calendar#MONDAY},
+     * <li> {@link java.util.Calendar#TUESDAY},
+     * <li> {@link java.util.Calendar#WEDNESDAY},
+     * <li> {@link java.util.Calendar#THURSDAY},
+     * <li> {@link java.util.Calendar#FRIDAY},
+     * <li> {@link java.util.Calendar#SATURDAY}
+     * </ul>
+     * <p>
+     * Note: If this extra is provided, {@link #EXTRA_DELETE_AFTER_USE} is ignored.
+     * </p>
+     */
+    public static final String EXTRA_DAYS = "android.intent.extra.alarm.DAYS";
+
+    /**
+     * Bundle extra: Whether or not to delete this alarm/timer after it's dismissed.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM} and {@link #ACTION_SET_TIMER}.
+     * </p><p>
+     * If this value is true, the alarm/timer used by this action should be deleted after it's been
+     * dismissed. The alarm/timer should only be removed if was actually created by the action. If
+     * an existing alarm/timer was used, it should not be deleted after it's dismissed.
+     * </p><p>
+     * The value is a {@link Boolean}.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #ACTION_SET_TIMER
+     */
+    public static final String EXTRA_DELETE_AFTER_USE = "android.intent.extra.alarm.DELETE_AFTER_USE";
+
+    /**
+     * Bundle extra: The hour of the alarm.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM}.
+     * </p><p>
+     * This extra is optional. If not provided, an implementation should open an activity
+     * that allows a user to set an alarm with user provided time.
+     * </p><p>
+     * The value is an {@link Integer} and ranges from 0 to 23.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #EXTRA_MINUTES
+     * @see #EXTRA_DAYS
      */
     public static final String EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
 
     /**
-     * Activity Extra: The minutes of the alarm being set.
+     * Bundle extra: The length of the timer in seconds.
      * <p>
-     * This value can be passed as an extra field to the Intent created with
-     * ACTION_SET_ALARM.  If it is not provided, the behavior is undefined and
-     * is up to the application.  The value is an integer and ranges from 0 to
-     * 59.
+     * Used by {@link #ACTION_SET_TIMER}.
+     * </p><p>
+     * This extra is optional. If not provided, an implementation should open an activity
+     * that allows a user to set a timer with user provided length.
+     * </p><p>
+     * The value is an {@link Integer} and ranges from 1 to 86400 (24 hours).
+     * </p>
+     *
+     * @see #ACTION_SET_TIMER
+     */
+    public static final String EXTRA_LENGTH = "android.intent.extra.alarm.LENGTH";
+
+    /**
+     * Bundle extra: A custom message for the alarm or timer.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM} and {@link #ACTION_SET_TIMER}.
+     * </p><p>
+     * The value is a {@link String}.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #ACTION_SET_TIMER
+     */
+    public static final String EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
+
+    /**
+     * Bundle extra: The minutes of the alarm.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM}.
+     * </p><p>
+     * The value is an {@link Integer} and ranges from 0 to 59. If not provided, it defaults to 0.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #EXTRA_HOUR
+     * @see #EXTRA_DAYS
      */
     public static final String EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
 
     /**
-     * Activity Extra: Optionally skip the application UI.
+     * Bundle extra: A ringtone to be played with this alarm.
      * <p>
-     * This value can be passed as an extra field to the Intent created with
-     * ACTION_SET_ALARM.  If true, the application is asked to bypass any
-     * intermediate UI and instead pop a toast indicating the result then
-     * finish the Activity.  If false, the application may display intermediate
-     * UI like a confirmation dialog or alarm settings.  The default is false.
+     * Used by {@link #ACTION_SET_ALARM}.
+     * </p><p>
+     * This value is a {@link String} and can either be set to {@link #VALUE_RINGTONE_SILENT} or
+     * to a content URI of the media to be played. If not specified or the URI doesn't exist,
+     * {@code "content://settings/system/alarm_alert} will be used.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #VALUE_RINGTONE_SILENT
+     * @see #EXTRA_VIBRATE
+     */
+    public static final String EXTRA_RINGTONE = "android.intent.extra.alarm.RINGTONE";
+
+    /**
+     * Bundle extra: Whether or not to display an activity after performing the action.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM} and {@link #ACTION_SET_TIMER}.
+     * </p><p>
+     * If true, the application is asked to bypass any intermediate UI. If false, the application
+     * may display intermediate UI like a confirmation dialog or settings.
+     * </p><p>
+     * The value is a {@link Boolean}. The default is {@code false}.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #ACTION_SET_TIMER
      */
     public static final String EXTRA_SKIP_UI = "android.intent.extra.alarm.SKIP_UI";
+
+    /**
+     * Bundle extra: Whether or not to activate the device vibrator.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM}.
+     * </p><p>
+     * The value is a {@link Boolean}. The default is {@code true}.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #EXTRA_RINGTONE
+     * @see #VALUE_RINGTONE_SILENT
+     */
+    public static final String EXTRA_VIBRATE = "android.intent.extra.alarm.VIBRATE";
+
+    /**
+     * Bundle extra value: Indicates no ringtone should be played.
+     * <p>
+     * Used by {@link #ACTION_SET_ALARM}, passed in through {@link #EXTRA_RINGTONE}.
+     * </p>
+     *
+     * @see #ACTION_SET_ALARM
+     * @see #EXTRA_RINGTONE
+     * @see #EXTRA_VIBRATE
+     */
+    public static final String VALUE_RINGTONE_SILENT = "silent";
 }
diff --git a/core/java/android/provider/Applications.java b/core/java/android/provider/Applications.java
deleted file mode 100644
index 7aabc50..0000000
--- a/core/java/android/provider/Applications.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.net.Uri;
-
-import java.util.List;
-
-/**
- * The Applications provider gives information about installed applications.
- *
- * @hide Only used by ApplicationsProvider so far.
- */
-public class Applications {
-
-    /**
-     * The content authority for this provider.
-     */
-    public static final String AUTHORITY = "applications";
-
-    /**
-     * The content:// style URL for this provider
-     */
-    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
-
-    /**
-     * The content path for application component URIs.
-     */
-    public static final String APPLICATION_PATH = "applications";
-
-    /**
-     * The content path for application search.
-     */
-    public static final String SEARCH_PATH = "search";
-
-    private static final String APPLICATION_SUB_TYPE = "vnd.android.application";
-
-    /**
-     * The MIME type for a single application item.
-     */
-    public static final String APPLICATION_ITEM_TYPE =
-            ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + APPLICATION_SUB_TYPE;
-
-    /**
-     * The MIME type for a list of application items.
-     */
-    public static final String APPLICATION_DIR_TYPE =
-            ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + APPLICATION_SUB_TYPE;
-
-    /**
-     * no public constructor since this is a utility class
-     */
-    private Applications() {}
-
-    /**
-     * Gets a cursor with application search results.
-     * See {@link ApplicationColumns} for the columns available in the returned cursor.
-     */
-    public static Cursor search(ContentResolver resolver, String query) {
-        Uri searchUri = CONTENT_URI.buildUpon().appendPath(SEARCH_PATH).appendPath(query).build();
-        return resolver.query(searchUri, null, null, null, null);
-    }
-
-    /**
-     * Gets the application component name from an application URI.
-     *
-     * @param appUri A URI of the form
-     * "content://applications/applications/&lt;packageName&gt;/&lt;className&gt;".
-     * @return The component name for the application, or
-     * <code>null</code> if the given URI was <code>null</code>
-     * or malformed.
-     */
-    public static ComponentName uriToComponentName(Uri appUri) {
-        if (appUri == null) return null;
-        if (!ContentResolver.SCHEME_CONTENT.equals(appUri.getScheme())) return null;
-        if (!AUTHORITY.equals(appUri.getAuthority())) return null;
-        List<String> pathSegments = appUri.getPathSegments();
-        if (pathSegments.size() != 3) return null;
-        if (!APPLICATION_PATH.equals(pathSegments.get(0))) return null;
-        String packageName = pathSegments.get(1);
-        String name = pathSegments.get(2);
-        return new ComponentName(packageName, name);
-    }
-
-    /**
-     * Gets the URI for an application component.
-     *
-     * @param packageName The name of the application's package.
-     * @param className The class name of the application.
-     * @return A URI of the form
-     * "content://applications/applications/&lt;packageName&gt;/&lt;className&gt;".
-     */
-    public static Uri componentNameToUri(String packageName, String className) {
-        return Applications.CONTENT_URI.buildUpon()
-                .appendEncodedPath(APPLICATION_PATH)
-                .appendPath(packageName)
-                .appendPath(className)
-                .build();
-    }
-
-    /**
-     * The columns in application cursors, like those returned by
-     * {@link Applications#search(ContentResolver, String)}.
-     */
-    public interface ApplicationColumns extends BaseColumns {
-        public static final String NAME = "name";
-        public static final String ICON = "icon";
-        public static final String URI = "uri";
-    }
-}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 91d349a..da7647a 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -38,7 +38,6 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.List;
 
 /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 585115a..b3309e1a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3269,6 +3269,23 @@
         public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
 
         /**
+         * Location access disabled
+         */
+        public static final int LOCATION_MODE_OFF = 0;
+        /**
+         * Network Location Provider disabled, but GPS and other sensors enabled.
+         */
+        public static final int LOCATION_MODE_SENSORS_ONLY = 1;
+        /**
+         * Reduced power usage, such as limiting the number of GPS updates per hour.
+         */
+        public static final int LOCATION_MODE_BATTERY_SAVING = 2;
+        /**
+         * Best-effort location computation allowed.
+         */
+        public static final int LOCATION_MODE_HIGH_ACCURACY = 3;
+
+        /**
          * A flag containing settings used for biometric weak
          * @hide
          */
@@ -4252,13 +4269,6 @@
          */
         public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
 
-        /**
-         * Whether or not to enable the dial pad autocomplete functionality.
-         *
-         * @hide
-         */
-        public static final String DIALPAD_AUTOCOMPLETE = "dialpad_autocomplete";
-
         /** @hide */
         public static final String BAR_SERVICE_COMPONENT = "bar_service_component";
 
@@ -4310,8 +4320,7 @@
             MOUNT_UMS_AUTOSTART,
             MOUNT_UMS_PROMPT,
             MOUNT_UMS_NOTIFY_ENABLED,
-            UI_NIGHT_MODE,
-            DIALPAD_AUTOCOMPLETE
+            UI_NIGHT_MODE
         };
 
         /**
@@ -4319,33 +4328,23 @@
          * @param cr the content resolver to use
          * @param provider the location provider to query
          * @return true if the provider is enabled
+         * @deprecated use {@link #getLocationMode(ContentResolver)}
          */
+        @Deprecated
         public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
             return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId());
         }
 
         /**
-         * Helper method for determining if the location master switch is enabled.
-         * @param cr the content resolver to use
-         * @return true if the master switch is enabled
-         * @hide
-         */
-        public static final boolean isLocationMasterSwitchEnabled(ContentResolver cr) {
-            int uid = UserHandle.myUserId();
-            synchronized (mLocationSettingsLock) {
-                return isLocationProviderEnabledForUser(cr, LocationManager.NETWORK_PROVIDER, uid)
-                        || isLocationProviderEnabledForUser(cr, LocationManager.GPS_PROVIDER, uid);
-            }
-        }
-
-        /**
          * Helper method for determining if a location provider is enabled.
          * @param cr the content resolver to use
          * @param provider the location provider to query
          * @param userId the userId to query
          * @return true if the provider is enabled
+         * @deprecated use {@link #getLocationModeForUser(ContentResolver, int)}
          * @hide
          */
+        @Deprecated
         public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
             String allowedProviders = Settings.Secure.getStringForUser(cr,
                     LOCATION_PROVIDERS_ALLOWED, userId);
@@ -4357,37 +4356,24 @@
          * @param cr the content resolver to use
          * @param provider the location provider to enable or disable
          * @param enabled true if the provider should be enabled
+         * @deprecated use {@link #setLocationMode(ContentResolver, int)}
          */
+        @Deprecated
         public static final void setLocationProviderEnabled(ContentResolver cr,
                 String provider, boolean enabled) {
             setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId());
         }
 
         /**
-         * Thread-safe method for enabling or disabling the location master switch.
-         *
-         * @param cr the content resolver to use
-         * @param enabled true if master switch should be enabled
-         * @hide
-         */
-        public static final void setLocationMasterSwitchEnabled(ContentResolver cr,
-                boolean enabled) {
-            int uid = UserHandle.myUserId();
-            synchronized (mLocationSettingsLock) {
-                setLocationProviderEnabledForUser(cr, LocationManager.GPS_PROVIDER, enabled, uid);
-                setLocationProviderEnabledForUser(cr, LocationManager.NETWORK_PROVIDER, enabled,
-                        uid);
-            }
-        }
-
-        /**
          * Thread-safe method for enabling or disabling a single location provider.
          * @param cr the content resolver to use
          * @param provider the location provider to enable or disable
          * @param enabled true if the provider should be enabled
          * @param userId the userId for which to enable/disable providers
+         * @deprecated use {@link #setLocationModeForUser(ContentResolver, int, int)}
          * @hide
          */
+        @Deprecated
         public static final void setLocationProviderEnabledForUser(ContentResolver cr,
                 String provider, boolean enabled, int userId) {
             synchronized (mLocationSettingsLock) {
@@ -4403,6 +4389,97 @@
                         userId);
             }
         }
+
+        /**
+         * Thread-safe method for setting the location mode to one of
+         * {@link #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY},
+         * {@link #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}.
+         *
+         * @param cr the content resolver to use
+         * @param mode such as {@link #LOCATION_MODE_HIGH_ACCURACY}
+         * @param userId the userId for which to change mode
+         *
+         * @throws IllegalArgumentException if mode is not one of the supported values
+         */
+        public static final void setLocationModeForUser(ContentResolver cr, int mode, int userId) {
+            synchronized (mLocationSettingsLock) {
+                boolean gps = false;
+                boolean network = false;
+                switch (mode) {
+                    case LOCATION_MODE_OFF:
+                        break;
+                    case LOCATION_MODE_SENSORS_ONLY:
+                        gps = true;
+                        break;
+                    case LOCATION_MODE_BATTERY_SAVING:
+                        network = true;
+                        break;
+                    case LOCATION_MODE_HIGH_ACCURACY:
+                        gps = true;
+                        network = true;
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Invalid location mode: " + mode);
+                }
+                Settings.Secure.setLocationProviderEnabledForUser(
+                        cr, LocationManager.GPS_PROVIDER, gps, userId);
+                Settings.Secure.setLocationProviderEnabledForUser(
+                        cr, LocationManager.NETWORK_PROVIDER, network, userId);
+            }
+        }
+
+        /**
+         * Thread-safe method for setting the location mode to one of
+         * {@link #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY},
+         * {@link #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}.
+         *
+         * @param cr the content resolver to use
+         * @param mode such as {@link #LOCATION_MODE_HIGH_ACCURACY}
+         *
+         * @throws IllegalArgumentException if mode is not one of the supported values
+         */
+        public static final void setLocationMode(ContentResolver cr, int mode) {
+            setLocationModeForUser(cr, mode, UserHandle.myUserId());
+        }
+
+        /**
+         * Thread-safe method for reading the location mode, returns one of
+         * {@link #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY},
+         * {@link #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}.
+         *
+         * @param cr the content resolver to use
+         * @param userId the userId for which to read the mode
+         * @return the location mode
+         */
+        public static final int getLocationModeForUser(ContentResolver cr, int userId) {
+            synchronized (mLocationSettingsLock) {
+                boolean gpsEnabled = Settings.Secure.isLocationProviderEnabledForUser(
+                        cr, LocationManager.GPS_PROVIDER, userId);
+                boolean networkEnabled = Settings.Secure.isLocationProviderEnabledForUser(
+                        cr, LocationManager.NETWORK_PROVIDER, userId);
+                if (gpsEnabled && networkEnabled) {
+                    return LOCATION_MODE_HIGH_ACCURACY;
+                } else if (gpsEnabled) {
+                    return LOCATION_MODE_SENSORS_ONLY;
+                } else if (networkEnabled) {
+                    return LOCATION_MODE_BATTERY_SAVING;
+                } else {
+                    return LOCATION_MODE_OFF;
+                }
+            }
+        }
+
+        /**
+         * Thread-safe method for reading the location mode, returns one of
+         * {@link #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY},
+         * {@link #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}.
+         *
+         * @param cr the content resolver to use
+         * @return the location mode
+         */
+        public static final int getLocationMode(ContentResolver cr) {
+            return getLocationModeForUser(cr, UserHandle.myUserId());
+        }
     }
 
     /**
@@ -5346,6 +5423,17 @@
          */
         public static final String CONNECTIVITY_CHANGE_DELAY = "connectivity_change_delay";
 
+
+        /**
+         * Network sampling interval, in seconds. We'll generate link information
+         * about bytes/packets sent and error rates based on data sampled in this interval
+         *
+         * @hide
+         */
+
+        public static final String CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS =
+                "connectivity_sampling_interval_in_seconds";
+
         /**
          * The series of successively longer delays used in retrying to download PAC file.
          * Last delay is used between successful PAC downloads.
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d2d1f1b..beefc21 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -776,7 +776,7 @@
     @Override
     public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
         Bitmap bitmap = patch.getBitmap();
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         // Shaders are ignored when drawing patches
         int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
         try {
@@ -791,7 +791,7 @@
     @Override
     public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
         Bitmap bitmap = patch.getBitmap();
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         // Shaders are ignored when drawing patches
         int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
         try {
@@ -808,7 +808,7 @@
 
     @Override
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         // Shaders are ignored when drawing bitmaps
         int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
         try {
@@ -824,7 +824,7 @@
 
     @Override
     public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         // Shaders are ignored when drawing bitmaps
         int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
         try {
@@ -841,7 +841,7 @@
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         // Shaders are ignored when drawing bitmaps
         int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
         try {
@@ -868,7 +868,7 @@
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         // Shaders are ignored when drawing bitmaps
         int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
         try {
@@ -944,7 +944,7 @@
     @Override
     public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
             int vertOffset, int[] colors, int colorOffset, Paint paint) {
-        if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps");
+        throwIfCannotDraw(bitmap);
         if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
             throw new ArrayIndexOutOfBoundsException();
         }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index e0786f7..409db84 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -36,7 +36,7 @@
             throws OutOfResourcesException;
     private static native int nativeCreateFromSurfaceControl(int surfaceControlNativeObject);
 
-    private static native void nativeLockCanvas(int nativeObject, Canvas canvas, Rect dirty)
+    private static native int nativeLockCanvas(int nativeObject, Canvas canvas, Rect dirty)
             throws OutOfResourcesException;
     private static native void nativeUnlockCanvasAndPost(int nativeObject, Canvas canvas);
 
@@ -72,6 +72,7 @@
     final Object mLock = new Object(); // protects the native state
     private String mName;
     int mNativeObject; // package scope only for SurfaceControl access
+    private int mLockedObject;
     private int mGenerationId; // incremented each time mNativeObject changes
     private final Canvas mCanvas = new CompatibleCanvas();
 
@@ -233,7 +234,14 @@
             throws OutOfResourcesException, IllegalArgumentException {
         synchronized (mLock) {
             checkNotReleasedLocked();
-            nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
+            if (mLockedObject != 0) {
+                // Ideally, nativeLockCanvas() would throw in this situation and prevent the
+                // double-lock, but that won't happen if mNativeObject was updated.  We can't
+                // abandon the old mLockedObject because it might still be in use, so instead
+                // we just refuse to re-lock the Surface.
+                throw new RuntimeException("Surface was already locked");
+            }
+            mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
             return mCanvas;
         }
     }
@@ -252,11 +260,21 @@
 
         synchronized (mLock) {
             checkNotReleasedLocked();
-            nativeUnlockCanvasAndPost(mNativeObject, canvas);
+            if (mNativeObject != mLockedObject) {
+                Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
+                        Integer.toHexString(mNativeObject) + ") != mLockedObject (0x" +
+                        Integer.toHexString(mLockedObject) +")");
+            }
+            if (mLockedObject == 0) {
+                throw new RuntimeException("Surface was not locked");
+            }
+            nativeUnlockCanvasAndPost(mLockedObject, canvas);
+            nativeRelease(mLockedObject);
+            mLockedObject = 0;
         }
     }
 
-    /** 
+    /**
      * @deprecated This API has been removed and is not supported.  Do not use.
      */
     @Deprecated
@@ -343,6 +361,10 @@
         }
 
         synchronized (mLock) {
+            // nativeReadFromParcel() will either return mNativeObject, or
+            // create a new native Surface and return it after reducing
+            // the reference count on mNativeObject.  Either way, it is
+            // not necessary to call nativeRelease() here.
             mName = source.readString();
             setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
         }
@@ -365,7 +387,8 @@
     @Override
     public String toString() {
         synchronized (mLock) {
-            return "Surface(name=" + mName + ")";
+            return "Surface(name=" + mName + ")/@0x" +
+                    Integer.toHexString(System.identityHashCode(this));
         }
     }
 
@@ -463,7 +486,7 @@
         public void getMatrix(Matrix m) {
             super.getMatrix(m);
             if (mOrigMatrix == null) {
-                mOrigMatrix = new Matrix(); 
+                mOrigMatrix = new Matrix();
             }
             mOrigMatrix.set(m);
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f05e372..5269ee3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2542,6 +2542,26 @@
 
     /**
      * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to specify that the hidden status bar would like to be shown.
+     */
+    public static final int STATUS_BAR_UNHIDE = 0x10000000;
+
+    /**
+     * @hide
+     *
+     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
+     * out of the public fields to keep the undefined bits out of the developer's way.
+     *
+     * Flag to specify that the hidden navigation bar would like to be shown.
+     */
+    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
+
+    /**
+     * @hide
      */
     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c874c82..d68c410 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3855,12 +3855,17 @@
      * the ViewGroup will be animated according to the animations defined in that LayoutTransition
      * object. By default, the transition object is null (so layout changes are not animated).
      *
+     * <p>Replacing a non-null transition will cause that previous transition to be
+     * canceled, if it is currently running, to restore this container to
+     * its correct post-transition state.</p>
+     *
      * @param transition The LayoutTransition object that will animated changes in layout. A value
      * of <code>null</code> means no transition will run on layout changes.
      * @attr ref android.R.styleable#ViewGroup_animateLayoutChanges
      */
     public void setLayoutTransition(LayoutTransition transition) {
         if (mTransition != null) {
+            mTransition.cancel();
             mTransition.removeTransitionListener(mLayoutTransitionListener);
         }
         mTransition = transition;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f711e7a..354e815 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5960,6 +5960,11 @@
         // Do nothing.
     }
 
+    void changeCanvasOpacity(boolean opaque) {
+        // TODO(romainguy): recreate Canvas (software or hardware) to reflect the opacity change.
+        Log.d(TAG, "changeCanvasOpacity: opaque=" + opaque);
+    }
+
     class TakenSurfaceHolder extends BaseSurfaceHolder {
         @Override
         public boolean onAllowLockCanvas() {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 3dd96f5..96c0ed2 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -494,6 +494,21 @@
             }
         }
     }
+
+    /** @hide */
+    public void changeCanvasOpacity(IBinder token, boolean opaque) {
+        if (token == null) {
+            return;
+        }
+        synchronized (mLock) {
+            for (int i = mParams.size() - 1; i >= 0; --i) {
+                if (mParams.get(i).token == token) {
+                    mRoots.get(i).changeCanvasOpacity(opaque);
+                    return;
+                }
+            }
+        }
+    }
 }
 
 final class WindowLeaked extends AndroidRuntimeException {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index e924e8b..6d54094 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -1341,7 +1341,6 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setScrollable(boolean scrollable) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
     }
 
@@ -1495,7 +1494,6 @@
      * @param liveRegion If the node is a live region.
      */
     public void setLiveRegion(boolean liveRegion) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_LIVE_REGION, liveRegion);
     }
 
@@ -1519,7 +1517,6 @@
      * @param multiLine True if the node is multi line.
      */
     public void setMultiLine(boolean multiLine) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
     }
 
@@ -1543,7 +1540,6 @@
      * @param opensPopup If the the node opens a popup.
      */
     public void setOpensPopup(boolean opensPopup) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
     }
 
@@ -1567,7 +1563,6 @@
      * @param expandable If the node can be expanded.
      */
     public void setExpandable(boolean expandable) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_EXPANDABLE, expandable);
     }
 
@@ -1591,7 +1586,6 @@
      * @param expanded If the node is expanded.
      */
     public void setExpanded(boolean expanded) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_EXPANDED, expanded);
     }
 
@@ -1615,7 +1609,6 @@
      * @param dismissable If the node can be dismissed.
      */
     public void setDismissable(boolean dismissable) {
-        enforceNotSealed();
         setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
     }
 
@@ -1929,6 +1922,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setInputType(int inputType) {
+        enforceNotSealed();
         mInputType = inputType;
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 03bde70..1b57d50 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -28,6 +28,7 @@
 import android.net.http.SslCertificate;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Looper;
 import android.os.Message;
 import android.os.StrictMode;
@@ -1043,24 +1044,26 @@
      * @param width          The page width. Should be larger than 0.
      * @param height         The page height. Should be larger than 0.
      * @param resultCallback A callback to be invoked when the PDF content is exported.
-     *                       A true indicates success, and a false failure.
+     *                       A true indicates success, and a false failure. Cannot be null.
+     * @param cancellationSignal Signal for cancelling the PDF conversion request. Must not
+     *                       be null.
      *
-     * TODO: explain method parameters, margins, consider making the callback
-     * return more meaningful information, explain any threading concerns, HW
-     * draw limitations, and make it public.
-     * TODO: at the moment we are asking app to provide paper size information (width
-     * and height). This is likely not ideal (I think need margin info too).
-     * Another approach would be using PrintAttributes. This is to be clarified later.
+     * The PDF conversion is done asynchronously and the PDF output is written to the provided
+     * outputstream. The caller should not close the outputstream until the resultCallback is
+     * called, indicating PDF conversion is complete. Webview cannot be drawn during the pdf
+     * export so the  application is recommended to take it offscreen, or putting in a layer
+     * with an overlaid progress UI / spinner.
      *
-     * TODO: explain this webview will not draw during export (onDraw will clear to
-     * background color) so recommend taking it offscreen, or putting in a layer with an
-     * overlaid progress UI / spinner.
+     * If the caller cancels the task using the cancellationSignal, the cancellation will be
+     * acked using the resultCallback signal.
+     *
+     * TODO(sgurun) margins, explain the units, make it public.
      * @hide
      */
     public void exportToPdf(OutputStream out, int width, int height,
-            ValueCallback<Boolean> resultCallback) {
+            ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
         checkThread();
-        mProvider.exportToPdf(out, width, height, resultCallback);
+        mProvider.exportToPdf(out, width, height, resultCallback, cancellationSignal);
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 228de5b..db98d30 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -57,6 +57,7 @@
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -2896,7 +2897,7 @@
      */
     @Override
     public void exportToPdf(java.io.OutputStream out, int width, int height,
-            ValueCallback<Boolean> resultCallback) {
+            ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
         // K-only API not implemented in WebViewClassic.
         throw new IllegalStateException("This API not supported on Android 4.3 and earlier");
 
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 7e6bac4..0fd4e33 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -29,13 +29,18 @@
  */
 public final class WebViewFactory {
     private static final boolean DEFAULT_TO_EXPERIMENTAL_WEBVIEW = true;
+    // REMEMBER: property names must be <= 31 chars total.
     private static final String EXPERIMENTAL_PROPERTY_DEFAULT_OFF = "persist.sys.webview.exp";
-    private static final String EXPERIMENTAL_PROPERTY_DEFAULT_ON  = "persist.sys.webview.exp_on";
+    private static final String EXPERIMENTAL_PROPERTY_DEFAULT_ON =
+            "persist.sys.webview." + Build.ID;
 
-    // Modify the persisted property name when the experiment is on-by-default, so that any user
-    // setting override lives in a different property namespace.
-    private static final String WEBVIEW_EXPERIMENTAL_PROPERTY = DEFAULT_TO_EXPERIMENTAL_WEBVIEW ?
-        EXPERIMENTAL_PROPERTY_DEFAULT_ON : EXPERIMENTAL_PROPERTY_DEFAULT_OFF;
+    // Modify the persisted property name when the new webview is on-by-default, so that any user
+    // setting override only lives as long as that build.
+    private static final String LONG_PROPERTY_NAME = DEFAULT_TO_EXPERIMENTAL_WEBVIEW ?
+            EXPERIMENTAL_PROPERTY_DEFAULT_ON : EXPERIMENTAL_PROPERTY_DEFAULT_OFF;
+    private static final String WEBVIEW_EXPERIMENTAL_PROPERTY =
+            LONG_PROPERTY_NAME.length() > SystemProperties.PROP_NAME_MAX ?
+            LONG_PROPERTY_NAME.substring(0, SystemProperties.PROP_NAME_MAX) : LONG_PROPERTY_NAME;
 
     private static final String FORCE_PROVIDER_PROPERTY = "webview.force_provider";
     private static final String FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM = "chromium";
@@ -80,8 +85,7 @@
 
     /** @hide */
     public static void setUseExperimentalWebView(boolean enable) {
-        SystemProperties.set(WebViewFactory.WEBVIEW_EXPERIMENTAL_PROPERTY,
-                enable ? "true" : "false");
+        SystemProperties.set(WEBVIEW_EXPERIMENTAL_PROPERTY, enable ? "true" : "false");
         Log.i(LOGTAG, "Use Experimental WebView changed: "
                 + SystemProperties.get(WebViewFactory.WEBVIEW_EXPERIMENTAL_PROPERTY, ""));
     }
@@ -92,6 +96,11 @@
             DEFAULT_TO_EXPERIMENTAL_WEBVIEW);
     }
 
+    /** @hide */
+    public static boolean isUseExperimentalWebViewSet() {
+        return !SystemProperties.get(WEBVIEW_EXPERIMENTAL_PROPERTY).isEmpty();
+    }
+
     static WebViewFactoryProvider getProvider() {
         synchronized (sProviderLock) {
             // For now the main purpose of this function (and the factory abstraction) is to keep
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 17b4061..8fe6edf 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -25,6 +25,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.http.SslCertificate;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Message;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -148,7 +149,7 @@
     public Picture capturePicture();
 
     public void exportToPdf(OutputStream out, int width, int height,
-            ValueCallback<Boolean> resultCallback);
+            ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal);
 
     public float getScale();
 
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 2037c3a..c070ee4 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -33,6 +33,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ActivityChooserModel.ActivityChooserModelClient;
 
 /**
@@ -229,6 +230,13 @@
 
         mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.expand_activities_button);
         mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
+        mExpandActivityOverflowButton.setAccessibilityDelegate(new AccessibilityDelegate() {
+            @Override
+            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                info.setOpensPopup(true);
+            }
+        });
         mExpandActivityOverflowButtonImage =
             (ImageView) mExpandActivityOverflowButton.findViewById(R.id.image);
         mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 2b4e520..8919248 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -33,6 +33,7 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.animation.AccelerateDecelerateInterpolator;
@@ -961,33 +962,6 @@
     }
 
     /**
-     * Receives motion events forwarded from a source view. This is used
-     * internally to implement support for drag-to-open.
-     *
-     * @param src view from which the event was forwarded
-     * @param srcEvent forwarded motion event in source-local coordinates
-     * @param activePointerId id of the pointer that activated forwarding
-     * @return whether the event was handled
-     * @hide
-     */
-    public boolean onForwardedEvent(View src, MotionEvent srcEvent, int activePointerId) {
-        final DropDownListView dst = mDropDownList;
-        if (dst == null || !dst.isShown()) {
-            return false;
-        }
-
-        // Convert event to local coordinates.
-        final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
-        src.toGlobalMotionEvent(dstEvent);
-        dst.toLocalMotionEvent(dstEvent);
-
-        // Forward converted event, then recycle it.
-        final boolean handled = dst.onForwardedEvent(dstEvent, activePointerId);
-        dstEvent.recycle();
-        return handled;
-    }
-
-    /**
      * <p>Builds the popup window's content and returns the height the popup
      * should have. Returns -1 when the content already exists.</p>
      *
@@ -1155,6 +1129,147 @@
     }
 
     /**
+     * Abstract class that forwards touch events to a {@link ListPopupWindow}.
+     *
+     * @hide
+     */
+    public static abstract class ForwardingListener implements View.OnTouchListener {
+        /** Scaled touch slop, used for detecting movement outside bounds. */
+        private final float mScaledTouchSlop;
+
+        /** Whether this listener is currently forwarding touch events. */
+        private boolean mForwarding;
+
+        /** The id of the first pointer down in the current event stream. */
+        private int mActivePointerId;
+
+        public ForwardingListener(Context context) {
+            mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        }
+
+        /**
+         * Returns the popup to which this listener is forwarding events.
+         * <p>
+         * Override this to return the correct popup. If the popup is displayed
+         * asynchronously, you may also need to override
+         * {@link #onForwardingStopped} to prevent premature cancelation of
+         * forwarding.
+         *
+         * @return the popup to which this listener is forwarding events
+         */
+        public abstract ListPopupWindow getPopup();
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            final boolean wasForwarding = mForwarding;
+            final boolean forwarding;
+            if (wasForwarding) {
+                forwarding = onTouchForwarded(v, event) || !onForwardingStopped();
+            } else {
+                forwarding = onTouchObserved(v, event) && onForwardingStarted();
+            }
+
+            mForwarding = forwarding;
+            return forwarding || wasForwarding;
+        }
+
+        /**
+         * Called when forwarding would like to start.
+         * <p>
+         * By default, this will show the popup returned by {@link #getPopup()}.
+         * It may be overridden to perform another action, like clicking the
+         * source view or preparing the popup before showing it.
+         *
+         * @return true to start forwarding, false otherwise
+         */
+        public boolean onForwardingStarted() {
+            final ListPopupWindow popup = getPopup();
+            if (popup != null && !popup.isShowing()) {
+                popup.show();
+            }
+            return true;
+        }
+
+        /**
+         * Called when forwarding would like to stop.
+         * <p>
+         * By default, this will dismiss the popup returned by
+         * {@link #getPopup()}. It may be overridden to perform some other
+         * action.
+         *
+         * @return true to stop forwarding, false otherwise
+         */
+        public boolean onForwardingStopped() {
+            final ListPopupWindow popup = getPopup();
+            if (popup != null && popup.isShowing()) {
+                popup.dismiss();
+            }
+            return true;
+        }
+
+        /**
+         * Observes motion events and determines when to start forwarding.
+         *
+         * @param src view from which the event originated
+         * @param srcEvent motion event in source view coordinates
+         * @return true to start forwarding motion events, false otherwise
+         */
+        private boolean onTouchObserved(View src, MotionEvent srcEvent) {
+            if (!src.isEnabled()) {
+                return false;
+            }
+
+            // The first pointer down is always the active pointer.
+            final int actionMasked = srcEvent.getActionMasked();
+            if (actionMasked == MotionEvent.ACTION_DOWN) {
+                mActivePointerId = srcEvent.getPointerId(0);
+            }
+
+            final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
+            if (activePointerIndex >= 0) {
+                final float x = srcEvent.getX(activePointerIndex);
+                final float y = srcEvent.getY(activePointerIndex);
+                if (!src.pointInView(x, y, mScaledTouchSlop)) {
+                    // The pointer has moved outside of the view.
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * Handled forwarded motion events and determines when to stop
+         * forwarding.
+         *
+         * @param src view from which the event originated
+         * @param srcEvent motion event in source view coordinates
+         * @return true to continue forwarding motion events, false to cancel
+         */
+        private boolean onTouchForwarded(View src, MotionEvent srcEvent) {
+            final ListPopupWindow popup = getPopup();
+            if (popup == null || !popup.isShowing()) {
+                return false;
+            }
+
+            final DropDownListView dst = popup.mDropDownList;
+            if (dst == null || !dst.isShown()) {
+                return false;
+            }
+
+            // Convert event to destination-local coordinates.
+            final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
+            src.toGlobalMotionEvent(dstEvent);
+            dst.toLocalMotionEvent(dstEvent);
+
+            // Forward converted event to destination view, then recycle it.
+            final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId);
+            dstEvent.recycle();
+            return handled;
+        }
+    }
+
+    /**
      * <p>Wrapper class for a ListView. This wrapper can hijack the focus to
      * make sure the list uses the appropriate drawables and states when
      * displayed on screen within a drop down. The focus is never actually
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index eec15a9..7c7df96 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -30,12 +30,14 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Gravity;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.ListPopupWindow.ForwardingListener;
 import android.widget.PopupWindow.OnDismissListener;
 
 
@@ -76,7 +78,10 @@
      * Use the theme-supplied value to select the dropdown mode.
      */
     private static final int MODE_THEME = -1;
-    
+
+    /** Forwarding listener used to implement drag-to-open. */
+    private ForwardingListener mForwardingListener;
+
     private SpinnerPopup mPopup;
     private DropDownAdapter mTempAdapter;
     int mDropDownWidth;
@@ -173,7 +178,7 @@
         }
 
         case MODE_DROPDOWN: {
-            DropdownPopup popup = new DropdownPopup(context, attrs, defStyle);
+            final DropdownPopup popup = new DropdownPopup(context, attrs, defStyle);
 
             mDropDownWidth = a.getLayoutDimension(
                     com.android.internal.R.styleable.Spinner_dropDownWidth,
@@ -193,6 +198,20 @@
             }
 
             mPopup = popup;
+            mForwardingListener = new ForwardingListener(context) {
+                @Override
+                public ListPopupWindow getPopup() {
+                    return popup;
+                }
+
+                @Override
+                public boolean onForwardingStarted() {
+                    if (!mPopup.isShowing()) {
+                        mPopup.show(getTextDirection(), getTextAlignment());
+                    }
+                    return true;
+                }
+            };
             break;
         }
         }
@@ -449,6 +468,15 @@
     }
 
     @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mForwardingListener != null && mForwardingListener.onTouch(this, event)) {
+            return true;
+        }
+
+        return super.onTouchEvent(event);
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) {
@@ -645,6 +673,10 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(Spinner.class.getName());
+
+        if (mAdapter != null) {
+            info.setOpensPopup(true);
+        }
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a315546..d5fc21c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8173,6 +8173,10 @@
                 info.addAction(AccessibilityNodeInfo.ACTION_CUT);
             }
         }
+
+        if (!isSingleLine()) {
+            info.setMultiLine(true);
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index b442ff5..d9e3ef6 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -65,7 +65,11 @@
         
         mH.sendMessage(msg);
     }
-    
+
+    public void sendMessageDelayed(Message msg, long delayMillis) {
+        mH.sendMessageDelayed(msg, delayMillis);
+    }
+
     public boolean hasMessages(int what) {
         return mH.hasMessages(what);
     }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 863d8cc..5d0a603 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -29,8 +29,11 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.View.MeasureSpec;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
+import android.widget.ListPopupWindow;
+import android.widget.ListPopupWindow.ForwardingListener;
 
 import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
@@ -561,7 +564,36 @@
             setFocusable(true);
             setVisibility(VISIBLE);
             setEnabled(true);
-            setOnTouchListener(new OverflowForwardListener(context));
+
+            setOnTouchListener(new ForwardingListener(context) {
+                @Override
+                public ListPopupWindow getPopup() {
+                    if (mOverflowPopup == null) {
+                        return null;
+                    }
+
+                    return mOverflowPopup.getPopup();
+                }
+
+                @Override
+                public boolean onForwardingStarted() {
+                    showOverflowMenu();
+                    return true;
+                }
+
+                @Override
+                public boolean onForwardingStopped() {
+                    // Displaying the popup occurs asynchronously, so wait for
+                    // the runnable to finish before deciding whether to stop
+                    // forwarding.
+                    if (mPostedOpenRunnable != null) {
+                        return false;
+                    }
+
+                    hideOverflowMenu();
+                    return true;
+                }
+            });
         }
 
         @Override
@@ -594,6 +626,12 @@
             }
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
+
+        @Override
+        public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+            super.onInitializeAccessibilityNodeInfo(info);
+            info.setOpensPopup(true);
+        }
     }
 
     private class OverflowPopup extends MenuPopupHelper {
@@ -680,56 +718,4 @@
             mPostedOpenRunnable = null;
         }
     }
-
-    private class OverflowForwardListener extends TouchForwardingListener {
-        /** Scaled touch slop, used for detecting movement outside bounds. */
-        private final float mScaledTouchSlop;
-
-        private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;
-
-        public OverflowForwardListener(Context context) {
-            mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        }
-
-        @Override
-        public boolean onTouchObserved(View src, MotionEvent srcEvent) {
-            if (!src.isEnabled()) {
-                return false;
-            }
-
-            // Always start forwarding events when the source view is touched.
-            mActivePointerId = srcEvent.getPointerId(0);
-            src.performClick();
-            return true;
-        }
-
-        @Override
-        public boolean onTouchForwarded(View src, MotionEvent srcEvent) {
-            final OverflowPopup popup = mOverflowPopup;
-            if (popup != null && popup.isShowing()) {
-                final int activePointerId = mActivePointerId;
-                if (activePointerId != MotionEvent.INVALID_POINTER_ID && src.isEnabled()
-                        && popup.forwardMotionEvent(src, srcEvent, activePointerId)) {
-                    // Handled the motion event, continue forwarding.
-                    return true;
-                }
-
-                final int activePointerIndex = srcEvent.findPointerIndex(activePointerId);
-                if (activePointerIndex >= 0) {
-                    final float x = srcEvent.getX(activePointerIndex);
-                    final float y = srcEvent.getY(activePointerIndex);
-                    if (src.pointInView(x, y, mScaledTouchSlop)) {
-                        // The user is touching the source view. Cancel
-                        // forwarding, but don't dismiss the popup.
-                        return false;
-                    }
-                }
-
-                popup.dismiss();
-            }
-
-            // Cancel forwarding.
-            return false;
-        }
-    }
 }
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index df579c69..85d9cbd 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -23,6 +23,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.ImageView;
@@ -269,4 +270,13 @@
         }
         return mInflater;
     }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+
+        if (mItemData != null && mItemData.hasSubMenu()) {
+            info.setOpensPopup(true);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 9b266df..dbb78c2 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -108,6 +108,10 @@
         }
     }
 
+    public ListPopupWindow getPopup() {
+        return mPopup;
+    }
+
     public boolean tryShow() {
         mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle);
         mPopup.setOnDismissListener(this);
@@ -159,22 +163,6 @@
         return mPopup != null && mPopup.isShowing();
     }
 
-    /**
-     * Forwards motion events from a source view to the popup window.
-     *
-     * @param src view from which the event was forwarded
-     * @param event forwarded motion event in source-local coordinates
-     * @param activePointerId id of the pointer that activated forwarding
-     * @return whether the event was handled
-     */
-    public boolean forwardMotionEvent(View src, MotionEvent event, int activePointerId) {
-        if (mPopup == null || !mPopup.isShowing()) {
-            return false;
-        }
-
-        return mPopup.onForwardedEvent(src, event, activePointerId);
-    }
-
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         MenuAdapter adapter = mAdapter;
diff --git a/core/java/com/android/internal/view/menu/TouchForwardingListener.java b/core/java/com/android/internal/view/menu/TouchForwardingListener.java
deleted file mode 100644
index d1086de..0000000
--- a/core/java/com/android/internal/view/menu/TouchForwardingListener.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * Touch listener used to intercept touches and forward them out of a view.
- */
-abstract class TouchForwardingListener implements View.OnTouchListener {
-    /** Whether this listener is currently forwarding touch events. */
-    private boolean mForwarding;
-
-    @Override
-    public boolean onTouch(View v, MotionEvent ev) {
-        final int actionMasked = ev.getActionMasked();
-
-        if (mForwarding) {
-            // Rejecting the event or ending the stream stops forwarding.
-            if (!onTouchForwarded(v, ev) || actionMasked == MotionEvent.ACTION_UP
-                    || actionMasked == MotionEvent.ACTION_CANCEL) {
-                stopForwarding();
-            }
-        } else {
-            if (onTouchObserved(v, ev)) {
-                startForwarding();
-            }
-        }
-
-        return mForwarding;
-    }
-
-    public void startForwarding() {
-        mForwarding = true;
-    }
-
-    public void stopForwarding() {
-        mForwarding = false;
-    }
-
-    /**
-     * Attempts to start forwarding motion events.
-     *
-     * @param v The view that triggered forwarding.
-     * @return True to start forwarding motion events, or false to cancel.
-     */
-    public abstract boolean onTouchObserved(View v, MotionEvent ev);
-
-    /**
-     * Handles forwarded motion events.
-     *
-     * @param v The view from which the event was forwarded.
-     * @param ev The forwarded motion event.
-     * @return True to continue forwarding motion events, or false to cancel.
-     */
-    public abstract boolean onTouchForwarded(View v, MotionEvent ev);
-}
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
new file mode 100644
index 0000000..13101512
--- /dev/null
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources.Theme;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Join;
+import android.graphics.Paint.Style;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.text.Layout.Alignment;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.accessibility.CaptioningManager.CaptionStyle;
+
+public class SubtitleView extends View {
+    // Ratio of inner padding to font size.
+    private static final float INNER_PADDING_RATIO = 0.125f;
+
+    // Styled dimensions.
+    private final float mCornerRadius;
+    private final float mOutlineWidth;
+    private final float mShadowRadius;
+    private final float mShadowOffsetX;
+    private final float mShadowOffsetY;
+
+    /** Temporary rectangle used for computing line bounds. */
+    private final RectF mLineBounds = new RectF();
+
+    /** Temporary array used for computing line wrapping. */
+    private float[] mTextWidths;
+
+    /** Reusable string builder used for holding text. */
+    private final StringBuilder mText = new StringBuilder();
+    private final StringBuilder mBreakText = new StringBuilder();
+
+    private TextPaint mPaint;
+
+    private int mForegroundColor;
+    private int mBackgroundColor;
+    private int mEdgeColor;
+    private int mEdgeType;
+
+    private boolean mHasMeasurements;
+    private int mLastMeasuredWidth;
+    private StaticLayout mLayout;
+
+    private float mSpacingMult = 1;
+    private float mSpacingAdd = 0;
+    private int mInnerPaddingX = 0;
+
+    public SubtitleView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SubtitleView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs);
+
+        final Theme theme = context.getTheme();
+        final TypedArray a = theme.obtainStyledAttributes(
+                    attrs, android.R.styleable.TextView, defStyle, 0);
+
+        CharSequence text = "";
+        int textSize = 15;
+
+        final int n = a.getIndexCount();
+        for (int i = 0; i < n; i++) {
+            int attr = a.getIndex(i);
+
+            switch (attr) {
+                case android.R.styleable.TextView_text:
+                    text = a.getText(attr);
+                    break;
+                case android.R.styleable.TextView_lineSpacingExtra:
+                    mSpacingAdd = a.getDimensionPixelSize(attr, (int) mSpacingAdd);
+                    break;
+                case android.R.styleable.TextView_lineSpacingMultiplier:
+                    mSpacingMult = a.getFloat(attr, mSpacingMult);
+                    break;
+                case android.R.styleable.TextAppearance_textSize:
+                    textSize = a.getDimensionPixelSize(attr, textSize);
+                    break;
+            }
+        }
+
+        // Set up density-dependent properties.
+        // TODO: Move these to a default style.
+        final Resources res = getContext().getResources();
+        final DisplayMetrics m = res.getDisplayMetrics();
+        mCornerRadius = res.getDimension(com.android.internal.R.dimen.subtitle_corner_radius);
+        mOutlineWidth = res.getDimension(com.android.internal.R.dimen.subtitle_outline_width);
+        mShadowRadius = res.getDimension(com.android.internal.R.dimen.subtitle_shadow_radius);
+        mShadowOffsetX = res.getDimension(com.android.internal.R.dimen.subtitle_shadow_offset);
+        mShadowOffsetY = mShadowOffsetX;
+
+        final TextPaint paint = new TextPaint();
+        paint.setAntiAlias(true);
+        paint.setSubpixelText(true);
+
+        mPaint = paint;
+
+        setText(text);
+        setTextSize(textSize);
+    }
+
+    public void setText(int resId) {
+        final CharSequence text = getContext().getText(resId);
+        setText(text);
+    }
+
+    public void setText(CharSequence text) {
+        mText.setLength(0);
+        mText.append(text);
+
+        mHasMeasurements = false;
+
+        requestLayout();
+    }
+
+    public void setForegroundColor(int color) {
+        mForegroundColor = color;
+
+        invalidate();
+    }
+
+    @Override
+    public void setBackgroundColor(int color) {
+        mBackgroundColor = color;
+
+        invalidate();
+    }
+
+    public void setEdgeType(int edgeType) {
+        mEdgeType = edgeType;
+
+        invalidate();
+    }
+
+    public void setEdgeColor(int color) {
+        mEdgeColor = color;
+
+        invalidate();
+    }
+
+    public void setTextSize(float size) {
+        final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+        final float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics);
+        if (mPaint.getTextSize() != size) {
+            mHasMeasurements = false;
+            mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f);
+            mPaint.setTextSize(size);
+
+            requestLayout();
+        }
+    }
+
+    public void setTypeface(Typeface typeface) {
+        if (mPaint.getTypeface() != typeface) {
+            mHasMeasurements = false;
+            mPaint.setTypeface(typeface);
+
+            requestLayout();
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int widthSpec = MeasureSpec.getSize(widthMeasureSpec);
+
+        if (computeMeasurements(widthSpec)) {
+            final StaticLayout layout = mLayout;
+
+            // Account for padding.
+            final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX * 2;
+            final int width = layout.getWidth() + paddingX;
+            final int height = layout.getHeight() + mPaddingTop + mPaddingBottom;
+            setMeasuredDimension(width, height);
+        } else {
+            setMeasuredDimension(MEASURED_STATE_TOO_SMALL, MEASURED_STATE_TOO_SMALL);
+        }
+    }
+
+    @Override
+    public void onLayout(boolean changed, int l, int t, int r, int b) {
+        final int width = r - l;
+
+        computeMeasurements(width);
+    }
+
+    private boolean computeMeasurements(int maxWidth) {
+        if (mHasMeasurements && maxWidth == mLastMeasuredWidth) {
+            return true;
+        }
+
+        // Account for padding.
+        final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX;
+        maxWidth -= paddingX;
+
+        if (maxWidth <= 0) {
+            return false;
+        }
+
+        final TextPaint paint = mPaint;
+        final CharSequence text = mText;
+        final int textLength = text.length();
+        if (mTextWidths == null || mTextWidths.length < textLength) {
+            mTextWidths = new float[textLength];
+        }
+
+        final float[] textWidths = mTextWidths;
+        paint.getTextWidths(text, 0, textLength, textWidths);
+
+        // Compute total length.
+        float runLength = 0;
+        for (int i = 0; i < textLength; i++) {
+            runLength += textWidths[i];
+        }
+
+        final int lineCount = (int) (runLength / maxWidth) + 1;
+        final int lineLength = (int) (runLength / lineCount);
+
+        // Build line break buffer.
+        final StringBuilder breakText = mBreakText;
+        breakText.setLength(0);
+
+        int line = 0;
+        int lastBreak = 0;
+        int maxRunLength = 0;
+        runLength = 0;
+        for (int i = 0; i < textLength; i++) {
+            if (runLength > lineLength) {
+                final CharSequence sequence = text.subSequence(lastBreak, i);
+                final int trimmedLength = TextUtils.getTrimmedLength(sequence);
+                breakText.append(sequence, 0, trimmedLength);
+                breakText.append('\n');
+                lastBreak = i;
+                runLength = 0;
+            }
+
+            runLength += textWidths[i];
+
+            if (runLength > maxRunLength) {
+                maxRunLength = (int) Math.ceil(runLength);
+            }
+        }
+        breakText.append(text.subSequence(lastBreak, textLength));
+
+        mHasMeasurements = true;
+        mLastMeasuredWidth = maxWidth;
+
+        mLayout = new StaticLayout(breakText, paint, maxRunLength, Alignment.ALIGN_LEFT,
+                mSpacingMult, mSpacingAdd, true);
+
+        return true;
+    }
+
+    public void setStyle(int styleId) {
+        final Context context = mContext;
+        final ContentResolver cr = context.getContentResolver();
+        final CaptionStyle style;
+        if (styleId == CaptionStyle.PRESET_CUSTOM) {
+            style = CaptionStyle.getCustomStyle(cr);
+        } else {
+            style = CaptionStyle.PRESETS[styleId];
+        }
+
+        mForegroundColor = style.foregroundColor;
+        mBackgroundColor = style.backgroundColor;
+        mEdgeType = style.edgeType;
+        mEdgeColor = style.edgeColor;
+        mHasMeasurements = false;
+
+        final Typeface typeface = style.getTypeface();
+        setTypeface(typeface);
+
+        requestLayout();
+    }
+
+    @Override
+    protected void onDraw(Canvas c) {
+        final StaticLayout layout = mLayout;
+        if (layout == null) {
+            return;
+        }
+
+        final int saveCount = c.save();
+        final int innerPaddingX = mInnerPaddingX;
+        c.translate(mPaddingLeft + innerPaddingX, mPaddingTop);
+
+        final RectF bounds = mLineBounds;
+        final int lineCount = layout.getLineCount();
+        final Paint paint = layout.getPaint();
+        paint.setShadowLayer(0, 0, 0, 0);
+
+        final int backgroundColor = mBackgroundColor;
+        if (Color.alpha(backgroundColor) > 0) {
+            paint.setColor(backgroundColor);
+            paint.setStyle(Style.FILL);
+
+            final float cornerRadius = mCornerRadius;
+            float previousBottom = layout.getLineTop(0);
+
+            for (int i = 0; i < lineCount; i++) {
+                bounds.left = layout.getLineLeft(i) - innerPaddingX;
+                bounds.right = layout.getLineRight(i) + innerPaddingX;
+                bounds.top = previousBottom;
+                bounds.bottom = layout.getLineBottom(i);
+
+                previousBottom = bounds.bottom;
+
+                c.drawRoundRect(bounds, cornerRadius, cornerRadius, paint);
+            }
+        }
+
+        final int edgeType = mEdgeType;
+        if (edgeType == CaptionStyle.EDGE_TYPE_OUTLINE) {
+            paint.setColor(mEdgeColor);
+            paint.setStyle(Style.FILL_AND_STROKE);
+            paint.setStrokeJoin(Join.ROUND);
+            paint.setStrokeWidth(mOutlineWidth);
+
+            for (int i = 0; i < lineCount; i++) {
+                layout.drawText(c, i, i);
+            }
+        }
+
+        if (edgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) {
+            paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mEdgeColor);
+        }
+
+        paint.setColor(mForegroundColor);
+        paint.setStyle(Style.FILL);
+
+        for (int i = 0; i < lineCount; i++) {
+            layout.drawText(c, i, i);
+        }
+
+        c.restoreToCount(saveCount);
+    }
+}
diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java
new file mode 100644
index 0000000..fa54c5f
--- /dev/null
+++ b/core/java/com/android/server/net/BaseNetworkObserver.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import android.net.INetworkManagementEventObserver;
+
+/**
+ * Base {@link INetworkManagementEventObserver} that provides no-op
+ * implementations which can be overridden.
+ *
+ * @hide
+ */
+public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {
+    @Override
+    public void interfaceStatusChanged(String iface, boolean up) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceRemoved(String iface) {
+        // default no-op
+    }
+
+    @Override
+    public void addressUpdated(String address, String iface, int flags, int scope) {
+        // default no-op
+    }
+
+    @Override
+    public void addressRemoved(String address, String iface, int flags, int scope) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceLinkStateChanged(String iface, boolean up) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceAdded(String iface) {
+        // default no-op
+    }
+
+    @Override
+    public void interfaceClassDataActivityChanged(String label, boolean active) {
+        // default no-op
+    }
+
+    @Override
+    public void limitReached(String limitName, String iface) {
+        // default no-op
+    }
+}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 8472705..a17b301 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -372,19 +372,6 @@
 }
 
 /*
- * We just want failed write() calls to just return with an error.
- */
-static void blockSigpipe()
-{
-    sigset_t mask;
-
-    sigemptyset(&mask);
-    sigaddset(&mask, SIGPIPE);
-    if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
-        ALOGW("WARNING: SIGPIPE not blocked\n");
-}
-
-/*
  * Read the persistent locale.
  */
 static void readLocale(char* language, char* region)
@@ -589,6 +576,12 @@
         mOptions.add(opt);
     }
 
+    property_get("ro.config.low_ram", propBuf, "");
+    if (strcmp(propBuf, "true") == 0) {
+      opt.optionString = "-XX:LowMemoryMode";
+      mOptions.add(opt);
+    }
+
     /*
      * Enable or disable dexopt features, such as bytecode verification and
      * calculation of register maps for precise GC.
@@ -814,8 +807,6 @@
     ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
             className != NULL ? className : "(unknown)");
 
-    blockSigpipe();
-
     /*
      * 'startSystemServer == true' means runtime is obsolete and not run from
      * init.rc anymore, so we print out the boot start event here.
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 0ea3bf7..fd9fbae 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -38,6 +38,23 @@
     }

 }

 

+static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,

+                          int, int) {

+    // SkColor's ordering may be different from SkPMColor

+    if (SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER) {

+        memcpy(dst, src, width * sizeof(SkColor));

+        return;

+    }

+

+    // order isn't same, repack each pixel manually

+    SkPMColor* d = (SkPMColor*)dst;

+    for (int i = 0; i < width; i++) {

+        SkColor c = *src++;

+        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),

+                                   SkColorGetG(c), SkColorGetB(c));

+    }

+}

+

 static void FromColor_D565(void* dst, const SkColor src[], int width,

                            int x, int y) {

     uint16_t* d = (uint16_t*)dst;

@@ -56,19 +73,35 @@
 

     DITHER_4444_SCAN(y);

     for (int stop = x + width; x < stop; x++) {

-        SkPMColor c = SkPreMultiplyColor(*src++);

-        *d++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));

-//        *d++ = SkPixel32ToPixel4444(c);

+        SkPMColor pmc = SkPreMultiplyColor(*src++);

+        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));

+//        *d++ = SkPixel32ToPixel4444(pmc);

+    }

+}

+

+static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,

+                            int x, int y) {

+    SkPMColor16* d = (SkPMColor16*)dst;

+

+    DITHER_4444_SCAN(y);

+    for (int stop = x + width; x < stop; x++) {

+        SkColor c = *src++;

+

+        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied

+        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),

+                                            SkColorGetG(c), SkColorGetB(c));

+        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));

+//        *d++ = SkPixel32ToPixel4444(pmc);

     }

 }

 

 // can return NULL

-static FromColorProc ChooseFromColorProc(SkBitmap::Config config) {

+static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {

     switch (config) {

         case SkBitmap::kARGB_8888_Config:

-            return FromColor_D32;

+            return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;

         case SkBitmap::kARGB_4444_Config:

-            return FromColor_D4444;

+            return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;

         case SkBitmap::kRGB_565_Config:

             return FromColor_D565;

         default:

@@ -77,13 +110,12 @@
     return NULL;

 }

 

-bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,

-                            int srcOffset, int srcStride,

-                            int x, int y, int width, int height,

-                            const SkBitmap& dstBitmap) {

+bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,

+        int x, int y, int width, int height,

+        const SkBitmap& dstBitmap, bool isPremultiplied) {

     SkAutoLockPixels alp(dstBitmap);

     void* dst = dstBitmap.getPixels();

-    FromColorProc proc = ChooseFromColorProc(dstBitmap.config());

+    FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);

 

     if (NULL == dst || NULL == proc) {

         return false;

@@ -122,6 +154,17 @@
     } while (--width != 0);

 }

 

+static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,

+                              SkColorTable*) {

+    SkASSERT(width > 0);

+    const SkPMColor* s = (const SkPMColor*)src;

+    do {

+        SkPMColor c = *s++;

+        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),

+                                SkGetPackedG32(c), SkGetPackedB32(c));

+    } while (--width != 0);

+}

+

 static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,

                                SkColorTable*) {

     SkASSERT(width > 0);

@@ -142,6 +185,17 @@
     } while (--width != 0);

 }

 

+static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,

+                                SkColorTable*) {

+    SkASSERT(width > 0);

+    const SkPMColor16* s = (const SkPMColor16*)src;

+    do {

+        SkPMColor c = SkPixel4444ToPixel32(*s++);

+        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),

+                                SkGetPackedG32(c), SkGetPackedB32(c));

+    } while (--width != 0);

+}

+

 static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,

                                  SkColorTable*) {

     SkASSERT(width > 0);

@@ -175,6 +229,19 @@
     ctable->unlockColors(false);

 }

 

+static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,

+                              SkColorTable* ctable) {

+    SkASSERT(width > 0);

+    const uint8_t* s = (const uint8_t*)src;

+    const SkPMColor* colors = ctable->lockColors();

+    do {

+        SkPMColor c = colors[*s++];

+        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),

+                                SkGetPackedG32(c), SkGetPackedB32(c));

+    } while (--width != 0);

+    ctable->unlockColors(false);

+}

+

 static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,

                                SkColorTable* ctable) {

     SkASSERT(width > 0);

@@ -189,19 +256,22 @@
 }

 

 // can return NULL

-static ToColorProc ChooseToColorProc(const SkBitmap& src) {

+static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {

     switch (src.config()) {

         case SkBitmap::kARGB_8888_Config:

-            return src.isOpaque() ? ToColor_S32_Opaque : ToColor_S32_Alpha;

+            if (src.isOpaque()) return ToColor_S32_Opaque;

+            return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;

         case SkBitmap::kARGB_4444_Config:

-            return src.isOpaque() ? ToColor_S4444_Opaque : ToColor_S4444_Alpha;

+            if (src.isOpaque()) return ToColor_S4444_Opaque;

+            return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;

         case SkBitmap::kRGB_565_Config:

             return ToColor_S565;

         case SkBitmap::kIndex8_Config:

             if (src.getColorTable() == NULL) {

                 return NULL;

             }

-            return src.isOpaque() ? ToColor_SI8_Opaque : ToColor_SI8_Alpha;

+            if (src.isOpaque()) return ToColor_SI8_Opaque;

+            return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;

         default:

             break;

     }

@@ -211,6 +281,12 @@
 ///////////////////////////////////////////////////////////////////////////////

 ///////////////////////////////////////////////////////////////////////////////

 

+static int getPremulBitmapCreateFlags(bool isMutable) {

+    int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;

+    if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;

+    return flags;

+}

+

 static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,

                               int offset, int stride, int width, int height,

                               SkBitmap::Config config, jboolean isMutable) {

@@ -236,10 +312,12 @@
     }

 

     if (jColors != NULL) {

-        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);

+        GraphicsJNI::SetPixels(env, jColors, offset, stride,

+                0, 0, width, height, bitmap, true);

     }

 

-    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);

+    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,

+            getPremulBitmapCreateFlags(isMutable), NULL, NULL);

 }

 

 static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,

@@ -250,8 +328,8 @@
     if (!src->copyTo(&result, dstConfig, &allocator)) {

         return NULL;

     }

-

-    return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL, NULL);

+    return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),

+            getPremulBitmapCreateFlags(isMutable), NULL, NULL);

 }

 

 static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {

@@ -347,14 +425,6 @@
     bitmap->eraseColor(color);

 }

 

-static int Bitmap_width(JNIEnv* env, jobject, SkBitmap* bitmap) {

-    return bitmap->width();

-}

-

-static int Bitmap_height(JNIEnv* env, jobject, SkBitmap* bitmap) {

-    return bitmap->height();

-}

-

 static int Bitmap_rowBytes(JNIEnv* env, jobject, SkBitmap* bitmap) {

     return bitmap->rowBytes();

 }

@@ -449,7 +519,9 @@
     bitmap->unlockPixels();

 

     blob.release();

-    return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, NULL, density);

+

+    return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),

+            NULL, NULL, density);

 }

 

 static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,

@@ -527,16 +599,17 @@
         env->ReleaseIntArrayElements(offsetXY, array, 0);

     }

 

-    return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL, NULL);

+    return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),

+            GraphicsJNI::kBitmapCreateFlag_Mutable, NULL, NULL);

 }

 

 ///////////////////////////////////////////////////////////////////////////////

 

 static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,

-                           int x, int y) {

+        int x, int y, bool isPremultiplied) {

     SkAutoLockPixels alp(*bitmap);

 

-    ToColorProc proc = ChooseToColorProc(*bitmap);

+    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);

     if (NULL == proc) {

         return 0;

     }

@@ -551,11 +624,11 @@
 }

 

 static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,

-                             jintArray pixelArray, int offset, int stride,

-                             int x, int y, int width, int height) {

+        jintArray pixelArray, int offset, int stride,

+        int x, int y, int width, int height, bool isPremultiplied) {

     SkAutoLockPixels alp(*bitmap);

 

-    ToColorProc proc = ChooseToColorProc(*bitmap);

+    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);

     if (NULL == proc) {

         return;

     }

@@ -578,13 +651,13 @@
 ///////////////////////////////////////////////////////////////////////////////

 

 static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,

-                            int x, int y, SkColor color) {

+        int x, int y, SkColor color, bool isPremultiplied) {

     SkAutoLockPixels alp(*bitmap);

     if (NULL == bitmap->getPixels()) {

         return;

     }

 

-    FromColorProc proc = ChooseFromColorProc(bitmap->config());

+    FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);

     if (NULL == proc) {

         return;

     }

@@ -594,10 +667,10 @@
 }

 

 static void Bitmap_setPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,

-                             jintArray pixelArray, int offset, int stride,

-                             int x, int y, int width, int height) {

+        jintArray pixelArray, int offset, int stride,

+        int x, int y, int width, int height, bool isPremultiplied) {

     GraphicsJNI::SetPixels(env, pixelArray, offset, stride,

-                           x, y, width, height, *bitmap);

+            x, y, width, height, *bitmap, isPremultiplied);

 }

 

 static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,

@@ -693,8 +766,6 @@
     {   "nativeCompress",           "(IIILjava/io/OutputStream;[B)Z",

         (void*)Bitmap_compress },

     {   "nativeErase",              "(II)V", (void*)Bitmap_erase },

-    {   "nativeWidth",              "(I)I", (void*)Bitmap_width },

-    {   "nativeHeight",             "(I)I", (void*)Bitmap_height },

     {   "nativeRowBytes",           "(I)I", (void*)Bitmap_rowBytes },

     {   "nativeConfig",             "(I)I", (void*)Bitmap_config },

     {   "nativeHasAlpha",           "(I)Z", (void*)Bitmap_hasAlpha },

@@ -709,10 +780,10 @@
     {   "nativeExtractAlpha",       "(II[I)Landroid/graphics/Bitmap;",

         (void*)Bitmap_extractAlpha },

     {   "nativeGenerationId",       "(I)I", (void*)Bitmap_getGenerationId },

-    {   "nativeGetPixel",           "(III)I", (void*)Bitmap_getPixel },

-    {   "nativeGetPixels",          "(I[IIIIIII)V", (void*)Bitmap_getPixels },

-    {   "nativeSetPixel",           "(IIII)V", (void*)Bitmap_setPixel },

-    {   "nativeSetPixels",          "(I[IIIIIII)V", (void*)Bitmap_setPixels },

+    {   "nativeGetPixel",           "(IIIZ)I", (void*)Bitmap_getPixel },

+    {   "nativeGetPixels",          "(I[IIIIIIIZ)V", (void*)Bitmap_getPixels },

+    {   "nativeSetPixel",           "(IIIIZ)V", (void*)Bitmap_setPixel },

+    {   "nativeSetPixels",          "(I[IIIIIIIZ)V", (void*)Bitmap_setPixels },

     {   "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",

                                             (void*)Bitmap_copyPixelsToBuffer },

     {   "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",

diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 49e3aa4..c433874 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -14,6 +14,7 @@
 #include "AutoDecodeCancel.h"
 #include "Utils.h"
 #include "JNIHelp.h"
+#include "GraphicsJNI.h"
 
 #include <android_runtime/AndroidRuntime.h>
 #include <androidfw/Asset.h>
@@ -25,6 +26,7 @@
 jfieldID gOptions_justBoundsFieldID;
 jfieldID gOptions_sampleSizeFieldID;
 jfieldID gOptions_configFieldID;
+jfieldID gOptions_premultipliedFieldID;
 jfieldID gOptions_mutableFieldID;
 jfieldID gOptions_ditherFieldID;
 jfieldID gOptions_purgeableFieldID;
@@ -213,6 +215,7 @@
     float scale = 1.0f;
     bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options));
     bool preferQualityOverSpeed = false;
+    bool requireUnpremultiplied = false;
 
     jobject javaBitmap = NULL;
 
@@ -233,6 +236,7 @@
         doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
         preferQualityOverSpeed = env->GetBooleanField(options,
                 gOptions_preferQualityOverSpeedFieldID);
+        requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
         javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
 
         if (env->GetBooleanField(options, gOptions_scaledFieldID)) {
@@ -256,6 +260,7 @@
     decoder->setSampleSize(sampleSize);
     decoder->setDitherImage(doDither);
     decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
+    decoder->setRequireUnpremultipliedColors(requireUnpremultiplied);
 
     SkBitmap* outputBitmap = NULL;
     unsigned int existingBufferSize = 0;
@@ -434,14 +439,20 @@
     adb.detach();
 
     if (javaBitmap != NULL) {
-        GraphicsJNI::reinitBitmap(env, javaBitmap);
+        bool isPremultiplied = !requireUnpremultiplied;
+        GraphicsJNI::reinitBitmap(env, javaBitmap, outputBitmap, isPremultiplied);
         outputBitmap->notifyPixelsChanged();
         // If a java bitmap was passed in for reuse, pass it back
         return javaBitmap;
     }
+
+    int bitmapCreateFlags = 0x0;
+    if (isMutable) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
+    if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
+
     // now create the java bitmap
     return GraphicsJNI::createBitmap(env, outputBitmap, javaAllocator.getStorageObj(),
-            isMutable, ninePatchChunk, layoutBounds, -1);
+            bitmapCreateFlags, ninePatchChunk, layoutBounds, -1);
 }
 
 static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
@@ -624,6 +635,7 @@
     gOptions_sampleSizeFieldID = getFieldIDCheck(env, options_class, "inSampleSize", "I");
     gOptions_configFieldID = getFieldIDCheck(env, options_class, "inPreferredConfig",
             "Landroid/graphics/Bitmap$Config;");
+    gOptions_premultipliedFieldID = getFieldIDCheck(env, options_class, "inPremultiplied", "Z");
     gOptions_mutableFieldID = getFieldIDCheck(env, options_class, "inMutable", "Z");
     gOptions_ditherFieldID = getFieldIDCheck(env, options_class, "inDither", "Z");
     gOptions_purgeableFieldID = getFieldIDCheck(env, options_class, "inPurgeable", "Z");
diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h
index f2aaab7..97dcc6d 100644
--- a/core/jni/android/graphics/BitmapFactory.h
+++ b/core/jni/android/graphics/BitmapFactory.h
@@ -7,6 +7,7 @@
 extern jfieldID gOptions_justBoundsFieldID;
 extern jfieldID gOptions_sampleSizeFieldID;
 extern jfieldID gOptions_configFieldID;
+extern jfieldID gOptions_premultipliedFieldID;
 extern jfieldID gOptions_ditherFieldID;
 extern jfieldID gOptions_purgeableFieldID;
 extern jfieldID gOptions_shareableFieldID;
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 10ef60a..0c0ebbb 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -201,6 +201,7 @@
     SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
     bool doDither = true;
     bool preferQualityOverSpeed = false;
+    bool requireUnpremultiplied = false;
 
     if (NULL != options) {
         sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
@@ -216,11 +217,13 @@
                 gOptions_preferQualityOverSpeedFieldID);
         // Get the bitmap for re-use if it exists.
         tileBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
+        requireUnpremultiplied = env->GetBooleanField(options, gOptions_premultipliedFieldID);
     }
 
     decoder->setDitherImage(doDither);
     decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
-    AutoDecoderCancel   adc(options, decoder);
+    decoder->setRequireUnpremultipliedColors(requireUnpremultiplied);
+    AutoDecoderCancel adc(options, decoder);
 
     // To fix the race condition in case "requestCancelDecode"
     // happens earlier than AutoDecoderCancel object is added
@@ -270,7 +273,10 @@
 
     JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator();
     jbyteArray buff = allocator->getStorageObjAndReset();
-    return GraphicsJNI::createBitmap(env, bitmap, buff, false, NULL, NULL, -1);
+
+    int bitmapCreateFlags = 0;
+    if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
+    return GraphicsJNI::createBitmap(env, bitmap, buff, bitmapCreateFlags, NULL, NULL, -1);
 }
 
 static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 6c4526e..813dd5a 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -547,18 +547,17 @@
                                 jboolean hasAlpha, SkPaint* paint)
     {
         SkBitmap    bitmap;
-        
         bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
                          SkBitmap::kRGB_565_Config, width, height);
         if (!bitmap.allocPixels()) {
             return;
         }
-        
+
         if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
-                                    0, 0, width, height, bitmap)) {
+                0, 0, width, height, bitmap, true)) {
             return;
         }
-        
+
         canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
                            paint);
     }
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 7c420ad..ef5b7c9 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -347,27 +347,32 @@
 ///////////////////////////////////////////////////////////////////////////////////////////
 
 jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
-                                  bool isMutable, jbyteArray ninepatch, jintArray layoutbounds,
-                                  int density)
+        int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density)
 {
     SkASSERT(bitmap);
     SkASSERT(bitmap->pixelRef());
+    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
+    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
+
     jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
-            static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)),
-            buffer, isMutable, ninepatch, layoutbounds, density);
+            static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), buffer,
+            bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied,
+            ninepatch, layoutbounds);
     hasException(env); // For the side effect of logging.
     return obj;
 }
 
-jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
-                            jbyteArray ninepatch, int density)
+jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
+        jbyteArray ninepatch, int density)
 {
-    return createBitmap(env, bitmap, NULL, isMutable, ninepatch, NULL, density);
+    return createBitmap(env, bitmap, NULL, bitmapCreateFlags, ninepatch, NULL, density);
 }
 
-void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap)
+void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
+        bool isPremultiplied)
 {
-    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID);
+    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
+            bitmap->width(), bitmap->height(), isPremultiplied);
 }
 
 int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
@@ -593,9 +598,8 @@
 
     gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
     gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
-    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
-                                            "(I[BZ[B[II)V");
-    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "()V");
+    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(I[BIIIZZ[B[I)V");
+    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
     gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
     gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
     gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index b676527..5a2a6f8 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -17,6 +17,12 @@
 
 class GraphicsJNI {
 public:
+    enum BitmapCreateFlags {
+        kBitmapCreateFlag_None = 0x0,
+        kBitmapCreateFlag_Mutable = 0x1,
+        kBitmapCreateFlag_Premultiplied = 0x2,
+    };
+
     // returns true if an exception is set (and dumps it out to the Log)
     static bool hasException(JNIEnv*);
 
@@ -53,13 +59,13 @@
         storage array (may be null).
     */
     static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
-                                bool isMutable, jbyteArray ninepatch, jintArray layoutbounds,
-                                int density = -1);
+            int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density = -1);
 
-    static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
-                                jbyteArray ninepatch, int density = -1);
+    static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
+            jbyteArray ninepatch, int density = -1);
 
-    static void reinitBitmap(JNIEnv* env, jobject javaBitmap);
+    static void reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
+            bool isPremultiplied);
 
     static int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap);
 
@@ -68,14 +74,14 @@
     static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
 
     static jbyteArray allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
-                                     SkColorTable* ctable);
+            SkColorTable* ctable);
 
     /** Copy the colors in colors[] to the bitmap, convert to the correct
         format along the way.
     */
     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
-                          int srcStride, int x, int y, int width, int height,
-                          const SkBitmap& dstBitmap);
+            int srcStride, int x, int y, int width, int height,
+            const SkBitmap& dstBitmap, bool isPremultiplied);
 
     static jbyteArray getBitmapStorageObj(SkPixelRef *pixref);
 };
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index 4383997..5276934 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -6,6 +6,7 @@
 #include <ScopedUtfChars.h>
 
 #include "EmojiFactory.h"
+#include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
 
 #include <dlfcn.h>
@@ -92,9 +93,6 @@
 static pthread_once_t g_once = PTHREAD_ONCE_INIT;
 static bool lib_emoji_factory_is_ready;
 
-static jclass    gBitmap_class;
-static jmethodID gBitmap_constructorMethodID;
-
 static jclass    gEmojiFactory_class;
 static jmethodID gEmojiFactory_constructorMethodID;
 
@@ -172,13 +170,8 @@
     return NULL;
   }
 
-  jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
-      static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), NULL, false, NULL, -1);
-  if (env->ExceptionCheck() != 0) {
-    ALOGE("*** Uncaught exception returned from Java call!\n");
-    env->ExceptionDescribe();
-  }
-  return obj;
+  return GraphicsJNI::createBitmap(env, bitmap,
+      GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
 }
 
 static void android_emoji_EmojiFactory_destructor(
@@ -281,9 +274,6 @@
 }
 
 int register_android_emoji_EmojiFactory(JNIEnv* env) {
-  gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
-  gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
-                                                 "(I[BZ[BI)V");
   gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
   gEmojiFactory_constructorMethodID = env->GetMethodID(
       gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 0018dd2..09d8d0f 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -553,7 +553,7 @@
         }
     }
 
-    if (camera->setPreviewTexture(gbp) != NO_ERROR) {
+    if (camera->setPreviewTarget(gbp) != NO_ERROR) {
         jniThrowException(env, "java/io/IOException", "setPreviewTexture failed");
     }
 }
@@ -576,7 +576,7 @@
 
     }
 
-    if (camera->setPreviewTexture(producer) != NO_ERROR) {
+    if (camera->setPreviewTarget(producer) != NO_ERROR) {
         jniThrowException(env, "java/io/IOException",
                 "setPreviewTexture failed");
     }
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index d6c5e4f..7d99464 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -41,11 +41,15 @@
 
 static int check_AudioSystem_Command(status_t status)
 {
-    if (status == NO_ERROR) {
+    switch (status) {
+    case DEAD_OBJECT:
+        return kAudioStatusMediaServerDied;
+    case NO_ERROR:
         return kAudioStatusOk;
-    } else {
-        return kAudioStatusError;
+    default:
+        break;
     }
+    return kAudioStatusError;
 }
 
 static int
@@ -112,61 +116,19 @@
     return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string());
 }
 
-static JNIEnv* AudioSystem_getJNIEnv(bool* needsDetach) {
-    *needsDetach = false;
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
-        JavaVM* vm = AndroidRuntime::getJavaVM();
-        int result = vm->AttachCurrentThread(&env, (void*) &args);
-        if (result != JNI_OK) {
-            ALOGE("thread attach failed: %#x", result);
-            return NULL;
-        }
-        *needsDetach = true;
-    }
-    return env;
-}
-
-static void AudioSystem_detachJNI() {
-    JavaVM* vm = AndroidRuntime::getJavaVM();
-    int result = vm->DetachCurrentThread();
-    if (result != JNI_OK) {
-        ALOGE("thread detach failed: %#x", result);
-    }
-}
-
 static void
 android_media_AudioSystem_error_callback(status_t err)
 {
-    bool needsDetach = false;
-    JNIEnv *env = AudioSystem_getJNIEnv(&needsDetach);
-
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
     if (env == NULL) {
         return;
     }
 
     jclass clazz = env->FindClass(kClassPathName);
 
-    int error;
-
-    switch (err) {
-    case DEAD_OBJECT:
-        error = kAudioStatusMediaServerDied;
-        break;
-    case NO_ERROR:
-        error = kAudioStatusOk;
-        break;
-    default:
-        error = kAudioStatusError;
-        break;
-    }
-
-    env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
-
-    if (needsDetach) {
-        AudioSystem_detachJNI();
-    }
+    env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
+                              "errorCallbackFromNative","(I)V"),
+                              check_AudioSystem_Command(err));
 }
 
 static int
@@ -313,6 +275,12 @@
     return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
 }
 
+static int
+android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
+{
+    return check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -340,6 +308,7 @@
     {"getPrimaryOutputFrameCount",   "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
     {"getOutputLatency",    "(I)I",     (void *)android_media_AudioSystem_getOutputLatency},
     {"setLowRamDevice",     "(Z)I",     (void *)android_media_AudioSystem_setLowRamDevice},
+    {"checkAudioFlinger",    "()I",     (void *)android_media_AudioSystem_checkAudioFlinger},
 };
 
 int register_android_media_AudioSystem(JNIEnv *env)
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 6d46cf9..dc90da73 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -417,7 +417,7 @@
         return;
     }
 
-    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
+    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap, true)) {
         delete bitmap;
         return;
     }
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 304514b..3f54fd7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -196,13 +196,13 @@
   SkSafeUnref(previousCanvas);
 }
 
-static void nativeLockCanvas(JNIEnv* env, jclass clazz,
+static jint nativeLockCanvas(JNIEnv* env, jclass clazz,
         jint nativeObject, jobject canvasObj, jobject dirtyRectObj) {
     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
 
     if (!isSurfaceValid(surface)) {
         doThrowIAE(env);
-        return;
+        return 0;
     }
 
     Rect dirtyRect;
@@ -223,7 +223,7 @@
                 OutOfResourcesException :
                 "java/lang/IllegalArgumentException";
         jniThrowException(env, exception, NULL);
-        return;
+        return 0;
     }
 
     // Associate a SkCanvas object to this surface
@@ -255,6 +255,13 @@
         env->SetIntField(dirtyRectObj, gRectClassInfo.right,  dirtyRect.right);
         env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
     }
+
+    // Create another reference to the surface and return it.  This reference
+    // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
+    // because the latter could be replaced while the surface is locked.
+    sp<Surface> lockedSurface(surface);
+    lockedSurface->incStrong(&sRefBaseOwner);
+    return (int) lockedSurface.get();
 }
 
 static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
@@ -351,7 +358,7 @@
             (void*)nativeIsValid },
     {"nativeIsConsumerRunningBehind", "(I)Z",
             (void*)nativeIsConsumerRunningBehind },
-    {"nativeLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V",
+    {"nativeLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)I",
             (void*)nativeLockCanvas },
     {"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
             (void*)nativeUnlockCanvasAndPost },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 19f56cd..67eade8 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -195,7 +195,8 @@
         bitmap->setPixels(NULL);
     }
 
-    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
+    return GraphicsJNI::createBitmap(env, bitmap,
+            GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
 }
 
 static void nativeScreenshot(JNIEnv* env, jclass clazz,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1363e3ca..5eb90f1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -108,6 +108,10 @@
     <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
     <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
+    <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
+    <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
+    <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
+    <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
     <protected-broadcast
         android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
@@ -121,7 +125,30 @@
     <protected-broadcast
         android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
+        android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+    <protected-broadcast
+        android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+    <protected-broadcast
         android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
+    <protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
+    <protected-broadcast android:name="android.btopp.intent.action.BT_OPP_HANDOVER_STARTED" />
+    <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
+    <protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
+    <protected-broadcast android:name="android.btopp.intent.action.BT_OPP_TRANSFER_PROGRESS" />
+    <protected-broadcast android:name="android.btopp.intent.action.LIST" />
+    <protected-broadcast android:name="android.btopp.intent.action.OPEN_OUTBOUND" />
+    <protected-broadcast android:name="android.btopp.intent.action.HIDE_COMPLETE" />
+    <protected-broadcast android:name="android.btopp.intent.action.CONFIRM" />
+    <protected-broadcast android:name="android.btopp.intent.action.HIDE" />
+    <protected-broadcast android:name="android.btopp.intent.action.BT_OPP_TRANSFER_DONE" />
+    <protected-broadcast android:name="android.btopp.intent.action.RETRY" />
+    <protected-broadcast android:name="android.btopp.intent.action.OPEN" />
+    <protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
+    <protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
+    <protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
+    <protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
+    <protected-broadcast android:name="com.android.bluetooth.pbap.authcancelled" />
 
     <protected-broadcast android:name="android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED" />
 
@@ -202,6 +229,8 @@
     <protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" />
     <protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
+    <protected-brodcast
+            android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
     <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE" />
     <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE" />
     <protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
@@ -218,6 +247,7 @@
     <protected-broadcast android:name="android.location.GPS_ENABLED_CHANGE" />
     <protected-broadcast android:name="android.location.PROVIDERS_CHANGED" />
     <protected-broadcast android:name="android.location.GPS_FIX_CHANGE" />
+    <protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
 
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
@@ -1617,6 +1647,14 @@
         android:label="@string/permlab_anyCodecForPlayback"
         android:description="@string/permdesc_anyCodecForPlayback" />
 
+    <!-- Allows an application to install and/or uninstall CA certificates on
+         behalf of the user.
+         @hide -->
+    <permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
+        android:protectionLevel="signature|system"
+        android:label="@string/permlab_manageCaCertificates"
+        android:description="@string/permdesc_manageCaCertificates" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png
new file mode 100644
index 0000000..8358392
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png
new file mode 100644
index 0000000..8c6e40c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png
new file mode 100644
index 0000000..f6c33dc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png
new file mode 100644
index 0000000..f32ca94
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png
new file mode 100644
index 0000000..da69ea5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png
new file mode 100644
index 0000000..18269a9c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png
new file mode 100644
index 0000000..469f736
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png
new file mode 100644
index 0000000..48be5cc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png
new file mode 100644
index 0000000..2e49b8d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png
new file mode 100644
index 0000000..8071886
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png
new file mode 100644
index 0000000..086069b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png
new file mode 100644
index 0000000..4074d81
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png
new file mode 100644
index 0000000..8ce58b3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png
new file mode 100644
index 0000000..fd92764
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png
new file mode 100644
index 0000000..8d64aa7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png
new file mode 100644
index 0000000..84155ccf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png
new file mode 100644
index 0000000..d48e27f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.png b/core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.png
new file mode 100644
index 0000000..47bc2b5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.png b/core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.png
new file mode 100644
index 0000000..3bd381d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png
new file mode 100644
index 0000000..95475ee
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png
new file mode 100644
index 0000000..e1c55ad
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png
new file mode 100644
index 0000000..6c49fe7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png
new file mode 100644
index 0000000..35a557e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png
new file mode 100644
index 0000000..7af87c8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png
new file mode 100644
index 0000000..0afe002
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..0707776
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png
new file mode 100644
index 0000000..e1553b7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png
new file mode 100644
index 0000000..e74b8b7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png
new file mode 100644
index 0000000..47a6373
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png
new file mode 100644
index 0000000..b0353feb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png
new file mode 100644
index 0000000..889a67c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_holo.png b/core/res/res/drawable-xxhdpi/btn_check_off_holo.png
new file mode 100644
index 0000000..cdcfdef
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png
new file mode 100644
index 0000000..ecfc08c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png
new file mode 100644
index 0000000..b067b58
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png
new file mode 100644
index 0000000..a54cfbf3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png
new file mode 100644
index 0000000..5afea71
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..d249372
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png
new file mode 100644
index 0000000..b544001
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png
new file mode 100644
index 0000000..eff125b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png
new file mode 100644
index 0000000..013c1f6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png
new file mode 100644
index 0000000..e0d942a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png
new file mode 100644
index 0000000..83f8dfd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_holo.png b/core/res/res/drawable-xxhdpi/btn_check_on_holo.png
new file mode 100644
index 0000000..6193147
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png
new file mode 100644
index 0000000..1aafc83
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png
new file mode 100644
index 0000000..11598dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
new file mode 100644
index 0000000..f4f58b7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png
new file mode 100644
index 0000000..c270562
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-xxhdpi/btn_code_lock_default_holo.png
new file mode 100755
index 0000000..1b6c9b5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-xxhdpi/btn_code_lock_touched_holo.png
new file mode 100755
index 0000000..dd13af8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..aea519c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..8ec4bf5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png
new file mode 100644
index 0000000..60732b3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png
new file mode 100644
index 0000000..12bac534
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png
new file mode 100644
index 0000000..b4c90d4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png
new file mode 100644
index 0000000..33c3ebb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png
new file mode 100644
index 0000000..f7bfd78
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png
new file mode 100644
index 0000000..7f5432f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png
new file mode 100644
index 0000000..c1632c8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png
new file mode 100644
index 0000000..6449593
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png
new file mode 100644
index 0000000..68be3c5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png
new file mode 100644
index 0000000..e3d3eb1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png
new file mode 100644
index 0000000..19706e0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png
new file mode 100644
index 0000000..af8eebb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png
new file mode 100644
index 0000000..54ff2c0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png
new file mode 100644
index 0000000..e3c4945
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png
new file mode 100644
index 0000000..bd04226
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png
new file mode 100644
index 0000000..f7aa79e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png
new file mode 100644
index 0000000..26f98fc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png
new file mode 100644
index 0000000..1ba39f2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png
new file mode 100644
index 0000000..531acc4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png
new file mode 100644
index 0000000..358f546
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..6c0f6f3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png
new file mode 100644
index 0000000..63ac52b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png
new file mode 100644
index 0000000..946936e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png
new file mode 100644
index 0000000..06f0cc7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png
new file mode 100644
index 0000000..abbf1ae
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png
new file mode 100644
index 0000000..28f5843
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png b/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png
new file mode 100644
index 0000000..c8ac939
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png
new file mode 100644
index 0000000..a7afd00
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png
new file mode 100644
index 0000000..43fac43
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png
new file mode 100644
index 0000000..9bc460f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png
new file mode 100644
index 0000000..96c63b1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..16b2023
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png
new file mode 100644
index 0000000..f03d07f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png
new file mode 100644
index 0000000..66b833d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png
new file mode 100644
index 0000000..adb7304
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png
new file mode 100644
index 0000000..cb7d6c8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png
new file mode 100644
index 0000000..12a0601
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png b/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png
new file mode 100644
index 0000000..2a11733
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png
new file mode 100644
index 0000000..f3ce811
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png
new file mode 100644
index 0000000..43142b6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png
new file mode 100644
index 0000000..de76d562b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png
new file mode 100644
index 0000000..d7eee84
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..292c752
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png
new file mode 100644
index 0000000..635c009
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png
new file mode 100644
index 0000000..fef0797
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png
new file mode 100644
index 0000000..c43977dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png
new file mode 100644
index 0000000..521dc80
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png
new file mode 100644
index 0000000..71a367b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png
new file mode 100644
index 0000000..35f72fa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png
new file mode 100644
index 0000000..c8541c3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png
new file mode 100644
index 0000000..899e577
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png
new file mode 100644
index 0000000..aaa6826
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..e699edc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png
new file mode 100644
index 0000000..a59c23c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png
new file mode 100644
index 0000000..d2504fb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png
new file mode 100644
index 0000000..d514bdd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png
new file mode 100644
index 0000000..53c7a53
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png
new file mode 100644
index 0000000..f942490
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png
new file mode 100644
index 0000000..11bae7c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png
new file mode 100644
index 0000000..08804b5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png
new file mode 100644
index 0000000..e15fc63
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png
new file mode 100644
index 0000000..cc82a54
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..853243d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png
new file mode 100644
index 0000000..b5cd0bb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png
new file mode 100644
index 0000000..bb16a5f7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png
new file mode 100644
index 0000000..c178a9b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png
new file mode 100644
index 0000000..886f395
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png
new file mode 100644
index 0000000..ab2b334
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png
new file mode 100644
index 0000000..59a8547
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png
new file mode 100644
index 0000000..14cac81
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png
new file mode 100644
index 0000000..b756e79
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png
new file mode 100644
index 0000000..89bf5b4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..7027cc2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png
new file mode 100644
index 0000000..d491c5b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png
new file mode 100644
index 0000000..f968b1a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png
new file mode 100644
index 0000000..1999f68
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png
new file mode 100644
index 0000000..ab4b58c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png
new file mode 100644
index 0000000..cd44fa6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png
new file mode 100644
index 0000000..8847d78
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png
new file mode 100644
index 0000000..3ef0498
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png
new file mode 100644
index 0000000..50e4940
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png
new file mode 100644
index 0000000..0b77905
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..e5ec283
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..5cd267d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png
new file mode 100644
index 0000000..c34c7af
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png
new file mode 100644
index 0000000..9b3900a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png
new file mode 100644
index 0000000..345fe9cd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png
new file mode 100644
index 0000000..b338843
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png
new file mode 100644
index 0000000..3f6ab80
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png
new file mode 100644
index 0000000..df71589
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png
new file mode 100644
index 0000000..2e21a6f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png
new file mode 100644
index 0000000..1a346c9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..ea15883
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..b403039
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png
new file mode 100644
index 0000000..f12643e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png
new file mode 100644
index 0000000..3090c9a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png
new file mode 100644
index 0000000..2fb4d91
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png
new file mode 100644
index 0000000..5e17dd5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png
new file mode 100644
index 0000000..bf9b997
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png
new file mode 100644
index 0000000..b36f670c6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png
new file mode 100644
index 0000000..d0c2151
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png
new file mode 100644
index 0000000..fab8dc1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png
new file mode 100644
index 0000000..8666113
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png
new file mode 100644
index 0000000..805927b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png
new file mode 100644
index 0000000..418f322
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png
new file mode 100644
index 0000000..a5a59d4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/combobox_disabled.png b/core/res/res/drawable-xxhdpi/combobox_disabled.png
new file mode 100644
index 0000000..d342344
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/combobox_nohighlight.png b/core/res/res/drawable-xxhdpi/combobox_nohighlight.png
new file mode 100644
index 0000000..377fbd3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/create_contact.png b/core/res/res/drawable-xxhdpi/create_contact.png
new file mode 100644
index 0000000..9baf195
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/create_contact.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png b/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png
new file mode 100644
index 0000000..6b22972
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png
new file mode 100644
index 0000000..0d2ba50
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png
new file mode 100644
index 0000000..13462d1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png
new file mode 100644
index 0000000..b029809
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png
new file mode 100644
index 0000000..63dd192
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png
new file mode 100644
index 0000000..ffe7cbf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png
new file mode 100644
index 0000000..f21e320
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png
new file mode 100644
index 0000000..87cf4d5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png
new file mode 100644
index 0000000..8d185f4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png
new file mode 100644
index 0000000..cb2ec6a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png
new file mode 100644
index 0000000..776dbfd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png
new file mode 100644
index 0000000..d922fd6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png
new file mode 100644
index 0000000..1298194
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png
new file mode 100644
index 0000000..baf7be3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png
new file mode 100644
index 0000000..f35251f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_angel.png b/core/res/res/drawable-xxhdpi/emo_im_angel.png
new file mode 100644
index 0000000..7d317e2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_cool.png b/core/res/res/drawable-xxhdpi/emo_im_cool.png
new file mode 100644
index 0000000..a05fabe
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_cool.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_crying.png b/core/res/res/drawable-xxhdpi/emo_im_crying.png
new file mode 100644
index 0000000..102800d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_crying.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png b/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png
new file mode 100644
index 0000000..6e5d226
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png
new file mode 100644
index 0000000..c328f8c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_happy.png b/core/res/res/drawable-xxhdpi/emo_im_happy.png
new file mode 100644
index 0000000..11e0163
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_kissing.png b/core/res/res/drawable-xxhdpi/emo_im_kissing.png
new file mode 100644
index 0000000..b929861
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_kissing.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_laughing.png b/core/res/res/drawable-xxhdpi/emo_im_laughing.png
new file mode 100644
index 0000000..4ed90bc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png
new file mode 100644
index 0000000..bcbcf8d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png b/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png
new file mode 100644
index 0000000..e17cf77
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_sad.png b/core/res/res/drawable-xxhdpi/emo_im_sad.png
new file mode 100644
index 0000000..0696d99
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_surprised.png b/core/res/res/drawable-xxhdpi/emo_im_surprised.png
new file mode 100644
index 0000000..bd821d7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_surprised.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png
new file mode 100644
index 0000000..af21474
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_undecided.png b/core/res/res/drawable-xxhdpi/emo_im_undecided.png
new file mode 100644
index 0000000..c43aa0b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_winking.png b/core/res/res/drawable-xxhdpi/emo_im_winking.png
new file mode 100644
index 0000000..41cdd23
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_wtf.png b/core/res/res/drawable-xxhdpi/emo_im_wtf.png
new file mode 100644
index 0000000..36f0b32
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_wtf.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_yelling.png b/core/res/res/drawable-xxhdpi/emo_im_yelling.png
new file mode 100644
index 0000000..db210eb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/emo_im_yelling.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png
new file mode 100644
index 0000000..fb41e44a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png b/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png
new file mode 100644
index 0000000..f3042a7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png
new file mode 100644
index 0000000..b1f006a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png b/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png
new file mode 100644
index 0000000..bac07f6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png
new file mode 100644
index 0000000..c9b5893
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png
new file mode 100644
index 0000000..a1326ed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png
new file mode 100644
index 0000000..91152ea
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png
new file mode 100644
index 0000000..1541e97
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png b/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png
new file mode 100644
index 0000000..d8335d5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png b/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png
new file mode 100644
index 0000000..cdc13e1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png
new file mode 100644
index 0000000..b9455ff
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png
new file mode 100644
index 0000000..a5c54dc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png
new file mode 100644
index 0000000..eaf0969
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png
new file mode 100644
index 0000000..9db45c0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png
new file mode 100644
index 0000000..04d1348
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png
new file mode 100644
index 0000000..962dba3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_action_assist_generic_activated.png b/core/res/res/drawable-xxhdpi/ic_action_assist_generic_activated.png
new file mode 100644
index 0000000..cc38e83
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_action_assist_generic_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_action_assist_generic_normal.png b/core/res/res/drawable-xxhdpi/ic_action_assist_generic_normal.png
new file mode 100644
index 0000000..42f96eb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_action_assist_generic_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm.png
new file mode 100755
index 0000000..c1c3d355
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png
new file mode 100644
index 0000000..4bcee68
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_bt.png b/core/res/res/drawable-xxhdpi/ic_audio_bt.png
new file mode 100755
index 0000000..140edac
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_bt.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png b/core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png
new file mode 100644
index 0000000..97829b4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_am.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_am.png
new file mode 100755
index 0000000..fb0e96e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_notification_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png
new file mode 100644
index 0000000..3aa7b53
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_phone_am.png b/core/res/res/drawable-xxhdpi/ic_audio_phone_am.png
new file mode 100644
index 0000000..1fd54a1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_phone_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png
new file mode 100644
index 0000000..699711c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png
new file mode 100644
index 0000000..19d92ba
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png
new file mode 100644
index 0000000..fdcfd56
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_am.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_am.png
new file mode 100755
index 0000000..15b6311
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_vol_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png
new file mode 100644
index 0000000..b8f4111
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_btn_search_go.png b/core/res/res/drawable-xxhdpi/ic_btn_search_go.png
new file mode 100644
index 0000000..1f4301d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png b/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png
new file mode 100644
index 0000000..b15f385
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png b/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png
new file mode 100644
index 0000000..a74c286
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png b/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png
new file mode 100644
index 0000000..a23a3ae
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png
new file mode 100644
index 0000000..fdecbe1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png
new file mode 100644
index 0000000..ca93e70
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png
new file mode 100644
index 0000000..6e48dc6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png
new file mode 100644
index 0000000..d26f75e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture.png b/core/res/res/drawable-xxhdpi/ic_contact_picture.png
new file mode 100644
index 0000000..b36ec17
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png
new file mode 100644
index 0000000..6e057ac
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png
new file mode 100644
index 0000000..4111bc5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png
new file mode 100644
index 0000000..52a69c3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png
new file mode 100644
index 0000000..5a41c23
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png
new file mode 100644
index 0000000..cdd6fd8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png
new file mode 100644
index 0000000..24ec28c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_emergency.png b/core/res/res/drawable-xxhdpi/ic_emergency.png
new file mode 100644
index 0000000..d070311d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_input_delete.png b/core/res/res/drawable-xxhdpi/ic_input_delete.png
new file mode 100644
index 0000000..ea047dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_input_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png
new file mode 100644
index 0000000..116b891
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png
new file mode 100644
index 0000000..5ca72ed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png
new file mode 100644
index 0000000..ed2d3c5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_lock.png b/core/res/res/drawable-xxhdpi/ic_lock_lock.png
new file mode 100644
index 0000000..1b8882c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_lock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_power_off.png b/core/res/res/drawable-xxhdpi/ic_lock_power_off.png
new file mode 100644
index 0000000..061dc78
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_power_off.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png
new file mode 100644
index 0000000..2cca958
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png
new file mode 100644
index 0000000..f53fa8f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png
new file mode 100644
index 0000000..78a560f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png
new file mode 100644
index 0000000..9c21761
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png
new file mode 100644
index 0000000..9298b61
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png
new file mode 100644
index 0000000..c41fe84
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png
new file mode 100644
index 0000000..3c29157
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 0000000..8b3458b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png
new file mode 100644
index 0000000..10cad65
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png
new file mode 100644
index 0000000..9fe0601
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 0000000..8e9d6d0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png
new file mode 100644
index 0000000..1d114b1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png
new file mode 100644
index 0000000..4db7876
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png
new file mode 100644
index 0000000..89aece4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png
new file mode 100644
index 0000000..4b99bad
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png
new file mode 100644
index 0000000..d1bd72e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png
new file mode 100644
index 0000000..ece563c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png
new file mode 100644
index 0000000..ff3dfa1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..c0edd91
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png
new file mode 100644
index 0000000..d03fc06
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png
new file mode 100644
index 0000000..76124a9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png
new file mode 100644
index 0000000..d0680dc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png
new file mode 100644
index 0000000..a5418d8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png
new file mode 100644
index 0000000..7528064
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_ime.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_ime.png
new file mode 100644
index 0000000..cb5d2fa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_ime.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..6dacccf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png
new file mode 100644
index 0000000..61db8cd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png
new file mode 100644
index 0000000..fd295ec
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png
new file mode 100644
index 0000000..a2e1b69
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png
new file mode 100644
index 0000000..d791ffa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png
new file mode 100644
index 0000000..3ba4331a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png
new file mode 100644
index 0000000..e469bf4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png
new file mode 100644
index 0000000..89b3213
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png
new file mode 100644
index 0000000..72bc5ee
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png
new file mode 100644
index 0000000..10cbb7e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png
new file mode 100644
index 0000000..0cf7307
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png
new file mode 100644
index 0000000..304996d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png
new file mode 100644
index 0000000..dbd5d48
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png
new file mode 100644
index 0000000..153bfa9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png b/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png
new file mode 100644
index 0000000..74ad3c8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_embed_play.png b/core/res/res/drawable-xxhdpi/ic_media_embed_play.png
new file mode 100644
index 0000000..3bf5a82
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_ff.png b/core/res/res/drawable-xxhdpi/ic_media_ff.png
new file mode 100644
index 0000000..ab9e022
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png b/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png
new file mode 100644
index 0000000..5734f16
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_next.png b/core/res/res/drawable-xxhdpi/ic_media_next.png
new file mode 100644
index 0000000..ce0a143
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_pause.png b/core/res/res/drawable-xxhdpi/ic_media_pause.png
new file mode 100644
index 0000000..9a36b17
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_play.png b/core/res/res/drawable-xxhdpi/ic_media_play.png
new file mode 100644
index 0000000..41f76bb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_previous.png b/core/res/res/drawable-xxhdpi/ic_media_previous.png
new file mode 100644
index 0000000..d468874
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_rew.png b/core/res/res/drawable-xxhdpi/ic_media_rew.png
new file mode 100644
index 0000000..8ebb2cc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
new file mode 100644
index 0000000..7b0c383
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
new file mode 100644
index 0000000..efb624e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
new file mode 100644
index 0000000..5ee57e4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
new file mode 100644
index 0000000..6bc2e4a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
new file mode 100644
index 0000000..c13af9c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
new file mode 100644
index 0000000..744fb42
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
new file mode 100644
index 0000000..ca4d59c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
new file mode 100644
index 0000000..fde5688a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
new file mode 100644
index 0000000..b8715c3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
new file mode 100644
index 0000000..668bb25
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
new file mode 100644
index 0000000..7f54a62
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
new file mode 100644
index 0000000..2df924d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_stop.png b/core/res/res/drawable-xxhdpi/ic_media_stop.png
new file mode 100644
index 0000000..c09989a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_account_list.png b/core/res/res/drawable-xxhdpi/ic_menu_account_list.png
new file mode 100644
index 0000000..e072523
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_add.png b/core/res/res/drawable-xxhdpi/ic_menu_add.png
new file mode 100644
index 0000000..18a83a1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_agenda.png b/core/res/res/drawable-xxhdpi/ic_menu_agenda.png
new file mode 100644
index 0000000..20f350b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png b/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png
new file mode 100644
index 0000000..c07a7c7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png
new file mode 100644
index 0000000..2decf65
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_archive.png b/core/res/res/drawable-xxhdpi/ic_menu_archive.png
new file mode 100644
index 0000000..a2d93b9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_attachment.png b/core/res/res/drawable-xxhdpi/ic_menu_attachment.png
new file mode 100644
index 0000000..a92f66b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_back.png b/core/res/res/drawable-xxhdpi/ic_menu_back.png
new file mode 100644
index 0000000..d3191ca
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_block.png b/core/res/res/drawable-xxhdpi/ic_menu_block.png
new file mode 100644
index 0000000..6b8f78d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png b/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png
new file mode 100644
index 0000000..096bfe4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png b/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png
new file mode 100644
index 0000000..18a83a1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_call.png b/core/res/res/drawable-xxhdpi/ic_menu_call.png
new file mode 100644
index 0000000..3b99ebb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_camera.png b/core/res/res/drawable-xxhdpi/ic_menu_camera.png
new file mode 100644
index 0000000..e09d050
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png b/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png
new file mode 100644
index 0000000..5f1b341
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png
new file mode 100644
index 0000000..92fdd99
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png
new file mode 100644
index 0000000..819e839
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_compass.png b/core/res/res/drawable-xxhdpi/ic_menu_compass.png
new file mode 100644
index 0000000..068678de
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_compose.png b/core/res/res/drawable-xxhdpi/ic_menu_compose.png
new file mode 100644
index 0000000..f4ccc2d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy.png b/core/res/res/drawable-xxhdpi/ic_menu_copy.png
new file mode 100644
index 0000000..222e083
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png
new file mode 100644
index 0000000..9dd56ef
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png
new file mode 100644
index 0000000..91043c9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_crop.png b/core/res/res/drawable-xxhdpi/ic_menu_crop.png
new file mode 100644
index 0000000..4cc11ca
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut.png b/core/res/res/drawable-xxhdpi/ic_menu_cut.png
new file mode 100644
index 0000000..81f45c6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png
new file mode 100644
index 0000000..1bec21c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png
new file mode 100644
index 0000000..0dfab90
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_day.png b/core/res/res/drawable-xxhdpi/ic_menu_day.png
new file mode 100644
index 0000000..6b92894
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_delete.png b/core/res/res/drawable-xxhdpi/ic_menu_delete.png
new file mode 100644
index 0000000..8e9e78d4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_directions.png b/core/res/res/drawable-xxhdpi/ic_menu_directions.png
new file mode 100644
index 0000000..f8a50c5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_edit.png b/core/res/res/drawable-xxhdpi/ic_menu_edit.png
new file mode 100644
index 0000000..2b6e967
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png b/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png
new file mode 100644
index 0000000..eae564f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png b/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png
new file mode 100644
index 0000000..dd94956
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find.png b/core/res/res/drawable-xxhdpi/ic_menu_find.png
new file mode 100644
index 0000000..32fad0a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png
new file mode 100644
index 0000000..f15e47a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png
new file mode 100644
index 0000000..61f6128
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_forward.png b/core/res/res/drawable-xxhdpi/ic_menu_forward.png
new file mode 100644
index 0000000..ca7eff9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png b/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png
new file mode 100644
index 0000000..920d687
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_gallery.png b/core/res/res/drawable-xxhdpi/ic_menu_gallery.png
new file mode 100644
index 0000000..3140ba9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_goto.png b/core/res/res/drawable-xxhdpi/ic_menu_goto.png
new file mode 100644
index 0000000..0d2109c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_help.png b/core/res/res/drawable-xxhdpi/ic_menu_help.png
new file mode 100644
index 0000000..a16ad70
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png
new file mode 100644
index 0000000..62c9eda
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_home.png b/core/res/res/drawable-xxhdpi/ic_menu_home.png
new file mode 100644
index 0000000..23c67d0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_info_details.png b/core/res/res/drawable-xxhdpi/ic_menu_info_details.png
new file mode 100644
index 0000000..4414bea
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_invite.png b/core/res/res/drawable-xxhdpi/ic_menu_invite.png
new file mode 100644
index 0000000..8020fd8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_login.png b/core/res/res/drawable-xxhdpi/ic_menu_login.png
new file mode 100644
index 0000000..2ac01e9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_manage.png b/core/res/res/drawable-xxhdpi/ic_menu_manage.png
new file mode 100644
index 0000000..733b759
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png b/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png
new file mode 100644
index 0000000..4d8c185
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_mark.png b/core/res/res/drawable-xxhdpi/ic_menu_mark.png
new file mode 100644
index 0000000..768aeb3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_month.png b/core/res/res/drawable-xxhdpi/ic_menu_month.png
new file mode 100644
index 0000000..b591a23
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_more.png b/core/res/res/drawable-xxhdpi/ic_menu_more.png
new file mode 100644
index 0000000..7e0bb5e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png
new file mode 100644
index 0000000..c3a1390
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png
new file mode 100644
index 0000000..9cddee4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png
new file mode 100644
index 0000000..826e724
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png
new file mode 100644
index 0000000..498a9ff
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png
new file mode 100644
index 0000000..d3d3f1a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png b/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png
new file mode 100644
index 0000000..a9285fe
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png b/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png
new file mode 100644
index 0000000..8ea61e1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png b/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png
new file mode 100644
index 0000000..85b3f20
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_notifications.png b/core/res/res/drawable-xxhdpi/ic_menu_notifications.png
new file mode 100644
index 0000000..d72a365
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste.png b/core/res/res/drawable-xxhdpi/ic_menu_paste.png
new file mode 100644
index 0000000..11f560c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png
new file mode 100644
index 0000000..d0b1fdb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png
new file mode 100644
index 0000000..27d01a69
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png b/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png
new file mode 100644
index 0000000..5c3b1e3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_preferences.png b/core/res/res/drawable-xxhdpi/ic_menu_preferences.png
new file mode 100644
index 0000000..b039537
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png b/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png
new file mode 100644
index 0000000..a3640a6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_refresh.png b/core/res/res/drawable-xxhdpi/ic_menu_refresh.png
new file mode 100644
index 0000000..580f4cf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_refresh.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_report_image.png b/core/res/res/drawable-xxhdpi/ic_menu_report_image.png
new file mode 100644
index 0000000..b8cf01e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_revert.png b/core/res/res/drawable-xxhdpi/ic_menu_revert.png
new file mode 100644
index 0000000..009cb91
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_rotate.png b/core/res/res/drawable-xxhdpi/ic_menu_rotate.png
new file mode 100644
index 0000000..fd6781f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_save.png b/core/res/res/drawable-xxhdpi/ic_menu_save.png
new file mode 100644
index 0000000..800da9a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search.png b/core/res/res/drawable-xxhdpi/ic_menu_search.png
new file mode 100644
index 0000000..22bb4c8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png
new file mode 100644
index 0000000..4ba4314
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png
new file mode 100644
index 0000000..c69d526
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png
new file mode 100644
index 0000000..9608411
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png
new file mode 100644
index 0000000..f66ab27
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_send.png b/core/res/res/drawable-xxhdpi/ic_menu_send.png
new file mode 100644
index 0000000..7674d24
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_set_as.png b/core/res/res/drawable-xxhdpi/ic_menu_set_as.png
new file mode 100644
index 0000000..667d723
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
new file mode 100644
index 0000000..5df7a55
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share.png b/core/res/res/drawable-xxhdpi/ic_menu_share.png
new file mode 100644
index 0000000..7b90639
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png
new file mode 100644
index 0000000..cc0cdda
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png
new file mode 100644
index 0000000..1e21d9d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png b/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png
new file mode 100644
index 0000000..5db7bc7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png
new file mode 100644
index 0000000..bb925f2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png
new file mode 100644
index 0000000..da3b4a7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_star.png b/core/res/res/drawable-xxhdpi/ic_menu_star.png
new file mode 100644
index 0000000..63ce68d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png b/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png
new file mode 100644
index 0000000..bb26e49
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_stop.png b/core/res/res/drawable-xxhdpi/ic_menu_stop.png
new file mode 100644
index 0000000..992738d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_today.png b/core/res/res/drawable-xxhdpi/ic_menu_today.png
new file mode 100644
index 0000000..b5d58d80
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_upload.png b/core/res/res/drawable-xxhdpi/ic_menu_upload.png
new file mode 100644
index 0000000..931e6ed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png
new file mode 100644
index 0000000..fd8f409
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_view.png b/core/res/res/drawable-xxhdpi/ic_menu_view.png
new file mode 100644
index 0000000..aff6c86
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_week.png b/core/res/res/drawable-xxhdpi/ic_menu_week.png
new file mode 100644
index 0000000..8da6b1e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_zoom.png b/core/res/res/drawable-xxhdpi/ic_menu_zoom.png
new file mode 100644
index 0000000..f6a5c30
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_ime_default.png b/core/res/res/drawable-xxhdpi/ic_notification_ime_default.png
new file mode 100644
index 0000000..6c8222e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notification_ime_default.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_media_route.png b/core/res/res/drawable-xxhdpi/ic_notification_media_route.png
new file mode 100644
index 0000000..da1a627
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notification_media_route.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xxhdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..fea4774
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_accounts.png b/core/res/res/drawable-xxhdpi/ic_perm_group_accounts.png
new file mode 100644
index 0000000..f30fcd4c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png b/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png
new file mode 100644
index 0000000..11f2638
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png b/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png
new file mode 100644
index 0000000..aaf8f76
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png b/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png
new file mode 100644
index 0000000..b302cc7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png b/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png
new file mode 100644
index 0000000..75aee05
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png b/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png
new file mode 100644
index 0000000..ad3629c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png b/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png
new file mode 100644
index 0000000..e22ffb8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png b/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png
new file mode 100644
index 0000000..0b48a24
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_display.png b/core/res/res/drawable-xxhdpi/ic_perm_group_display.png
new file mode 100644
index 0000000..29e6332
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png b/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png
new file mode 100644
index 0000000..afe137a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_location.png b/core/res/res/drawable-xxhdpi/ic_perm_group_location.png
new file mode 100644
index 0000000..7124634
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png b/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png
new file mode 100644
index 0000000..9534dcb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png b/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png
new file mode 100644
index 0000000..723a2cf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_network.png b/core/res/res/drawable-xxhdpi/ic_perm_group_network.png
new file mode 100644
index 0000000..703b25b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png b/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png
new file mode 100644
index 0000000..2428976
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png b/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png
new file mode 100644
index 0000000..67e523c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png b/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png
new file mode 100644
index 0000000..d660740
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png b/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png
new file mode 100644
index 0000000..3aae345
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png b/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png
new file mode 100644
index 0000000..a3d7b26
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png b/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png
new file mode 100644
index 0000000..e260acf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_storage.png b/core/res/res/drawable-xxhdpi/ic_perm_group_storage.png
new file mode 100644
index 0000000..d3937db
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png b/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png
new file mode 100644
index 0000000..41ef06b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png b/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png
new file mode 100644
index 0000000..5a89628
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png b/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png
new file mode 100644
index 0000000..cee2b05
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary.png b/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary.png
new file mode 100644
index 0000000..8c2cd17
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary_write.png b/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary_write.png
new file mode 100644
index 0000000..121d6cf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png b/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png
new file mode 100644
index 0000000..118c140
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png b/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png
new file mode 100644
index 0000000..f95cd9d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_suggestions_add.png b/core/res/res/drawable-xxhdpi/ic_suggestions_add.png
new file mode 100644
index 0000000..b880d40
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_suggestions_add.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png b/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png
new file mode 100644
index 0000000..f9e2702
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_text_dot.png b/core/res/res/drawable-xxhdpi/ic_text_dot.png
new file mode 100644
index 0000000..a74c286
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_text_dot.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_default_holo.png
new file mode 100644
index 0000000..a11b6dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_green_holo.png
new file mode 100644
index 0000000..eae7ea8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_red_holo.png
new file mode 100644
index 0000000..f6c3e27
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_input_error.png b/core/res/res/drawable-xxhdpi/indicator_input_error.png
new file mode 100644
index 0000000..b5a6eaf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_add_widget.png b/core/res/res/drawable-xxhdpi/kg_add_widget.png
new file mode 100644
index 0000000..33d839e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_add_widget.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_add_widget_disabled.png b/core/res/res/drawable-xxhdpi/kg_add_widget_disabled.png
new file mode 100644
index 0000000..405ab30
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_add_widget_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_add_widget_pressed.png b/core/res/res/drawable-xxhdpi/kg_add_widget_pressed.png
new file mode 100644
index 0000000..f23fad5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_add_widget_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_bouncer_bg_focused.9.png b/core/res/res/drawable-xxhdpi/kg_bouncer_bg_focused.9.png
new file mode 100644
index 0000000..67e5900
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_bouncer_bg_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_bouncer_bg_normal.9.png b/core/res/res/drawable-xxhdpi/kg_bouncer_bg_normal.9.png
new file mode 100644
index 0000000..b474e7d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_bouncer_bg_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_bouncer_bg_pressed.9.png b/core/res/res/drawable-xxhdpi/kg_bouncer_bg_pressed.9.png
new file mode 100644
index 0000000..5edf225
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_bouncer_bg_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_dot_pattern.png b/core/res/res/drawable-xxhdpi/kg_dot_pattern.png
new file mode 100644
index 0000000..2ce3ba2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_dot_pattern.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_security_grip.9.png b/core/res/res/drawable-xxhdpi/kg_security_grip.9.png
new file mode 100644
index 0000000..47fd407
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_security_grip.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_security_lock_focused.png b/core/res/res/drawable-xxhdpi/kg_security_lock_focused.png
new file mode 100644
index 0000000..e0a2e2a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_security_lock_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_security_lock_normal.png b/core/res/res/drawable-xxhdpi/kg_security_lock_normal.png
new file mode 100644
index 0000000..2d62c45
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_security_lock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_security_lock_pressed.png b/core/res/res/drawable-xxhdpi/kg_security_lock_pressed.png
new file mode 100644
index 0000000..97900d5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_security_lock_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/kg_widget_bg_padded.9.png b/core/res/res/drawable-xxhdpi/kg_widget_bg_padded.9.png
new file mode 100644
index 0000000..a22bc8e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/kg_widget_bg_padded.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_activated_holo.9.png b/core/res/res/drawable-xxhdpi/list_activated_holo.9.png
new file mode 100644
index 0000000..9f08bb0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png
new file mode 100644
index 0000000..9678825
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png
new file mode 100644
index 0000000..c69a6a3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_focused_holo.9.png b/core/res/res/drawable-xxhdpi/list_focused_holo.9.png
new file mode 100644
index 0000000..76cad17
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png b/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png
new file mode 100644
index 0000000..8f436ea
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png
new file mode 100644
index 0000000..7bfdd34
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png
new file mode 100644
index 0000000..13f76de
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png
new file mode 100644
index 0000000..61f8915
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png
new file mode 100644
index 0000000..5ae4882
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png
new file mode 100644
index 0000000..a1b5ed2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png
new file mode 100644
index 0000000..7cfb33d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png
new file mode 100644
index 0000000..e662b69
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png
new file mode 100644
index 0000000..5167387
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png
new file mode 100644
index 0000000..4d83885
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png
new file mode 100644
index 0000000..2f93cbf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png b/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png
new file mode 100644
index 0000000..5521eb6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png b/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png
new file mode 100644
index 0000000..09ee1c3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png
new file mode 100644
index 0000000..e87e372
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png
new file mode 100644
index 0000000..6ca7814
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png
new file mode 100644
index 0000000..c933eab
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png
new file mode 100644
index 0000000..112f939
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png
new file mode 100644
index 0000000..90489bc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png
new file mode 100644
index 0000000..472c3d3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..6f0a88c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png
new file mode 100644
index 0000000..ea965c5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png
new file mode 100644
index 0000000..822df62
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png
new file mode 100644
index 0000000..b17dd91
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png
new file mode 100644
index 0000000..b558db7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png
new file mode 100644
index 0000000..5121bc0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png
new file mode 100644
index 0000000..166e08c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png
new file mode 100644
index 0000000..166e08c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png
new file mode 100644
index 0000000..3f2e813
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png
new file mode 100644
index 0000000..9026c12
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png
new file mode 100644
index 0000000..2a24398
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png
new file mode 100644
index 0000000..2a24398
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png b/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png
new file mode 100644
index 0000000..b7a9940
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..a4eb1a5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png
new file mode 100644
index 0000000..b43b0c2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png
new file mode 100644
index 0000000..81b68fc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png
new file mode 100644
index 0000000..91b2f2f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png
new file mode 100644
index 0000000..82da07e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png
new file mode 100644
index 0000000..d7c2f34
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png
new file mode 100644
index 0000000..1bc2bf1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png
new file mode 100644
index 0000000..1bc2bf1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png
new file mode 100644
index 0000000..0fd9b05
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png
new file mode 100644
index 0000000..9f6a470
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png
new file mode 100644
index 0000000..35905ea
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png
new file mode 100644
index 0000000..35905ea
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/overscroll_edge.png b/core/res/res/drawable-xxhdpi/overscroll_edge.png
new file mode 100644
index 0000000..1a92737
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/overscroll_glow.png b/core/res/res/drawable-xxhdpi/overscroll_glow.png
new file mode 100644
index 0000000..c187e95
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png
new file mode 100644
index 0000000..8993469
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png
new file mode 100644
index 0000000..38ec76c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/pointer_arrow.png b/core/res/res/drawable-xxhdpi/pointer_arrow.png
new file mode 100644
index 0000000..65e0320
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png
new file mode 100644
index 0000000..251660a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png
new file mode 100644
index 0000000..12b1e64
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png
new file mode 100644
index 0000000..5d389af
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png
new file mode 100644
index 0000000..5e3c01b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_audio_away.png b/core/res/res/drawable-xxhdpi/presence_audio_away.png
new file mode 100644
index 0000000..e8e2b1a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_audio_busy.png b/core/res/res/drawable-xxhdpi/presence_audio_busy.png
new file mode 100644
index 0000000..824b5be
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_audio_online.png b/core/res/res/drawable-xxhdpi/presence_audio_online.png
new file mode 100644
index 0000000..6b3cd2d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_away.png b/core/res/res/drawable-xxhdpi/presence_away.png
new file mode 100644
index 0000000..217f4e9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_busy.png b/core/res/res/drawable-xxhdpi/presence_busy.png
new file mode 100644
index 0000000..9416720
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_invisible.png b/core/res/res/drawable-xxhdpi/presence_invisible.png
new file mode 100644
index 0000000..72ada9c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_offline.png b/core/res/res/drawable-xxhdpi/presence_offline.png
new file mode 100644
index 0000000..bc71d3a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_online.png b/core/res/res/drawable-xxhdpi/presence_online.png
new file mode 100644
index 0000000..501a75d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_video_away.png b/core/res/res/drawable-xxhdpi/presence_video_away.png
new file mode 100644
index 0000000..1379bc0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_video_busy.png b/core/res/res/drawable-xxhdpi/presence_video_busy.png
new file mode 100644
index 0000000..d90297c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_video_online.png b/core/res/res/drawable-xxhdpi/presence_video_online.png
new file mode 100644
index 0000000..4186408
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png
new file mode 100644
index 0000000..2e8c2e5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png
new file mode 100644
index 0000000..fb146c3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png
new file mode 100644
index 0000000..36078f9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png
new file mode 100644
index 0000000..add4d38
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png
new file mode 100644
index 0000000..90b56fc8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png
new file mode 100644
index 0000000..28b53dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png
new file mode 100644
index 0000000..e751345
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png
new file mode 100644
index 0000000..663965f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png
new file mode 100644
index 0000000..3574c9a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png
new file mode 100644
index 0000000..a289d33
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png
new file mode 100644
index 0000000..6fa2fbb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png
new file mode 100644
index 0000000..0117543
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png
new file mode 100644
index 0000000..681fe1d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png
new file mode 100644
index 0000000..bbc3999
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
new file mode 100644
index 0000000..8eda0f1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png
new file mode 100644
index 0000000..c7cd27a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
new file mode 100644
index 0000000..09c8cbd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png
new file mode 100644
index 0000000..d0a5a71
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
new file mode 100644
index 0000000..8a67108
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
new file mode 100644
index 0000000..f84557f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png
new file mode 100644
index 0000000..ede3db5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png
new file mode 100644
index 0000000..906dbe1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png
new file mode 100644
index 0000000..cff58d3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png
new file mode 100644
index 0000000..7e1a770
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png
new file mode 100644
index 0000000..ab3f4d3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png
new file mode 100644
index 0000000..ab7a496
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png
new file mode 100644
index 0000000..8bb8aa0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png
new file mode 100644
index 0000000..44e6696
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png
new file mode 100644
index 0000000..94ec824
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png
new file mode 100644
index 0000000..0a12fc9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png
new file mode 100644
index 0000000..4894658
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png
new file mode 100644
index 0000000..4bb8a73
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png
new file mode 100644
index 0000000..9e215d7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png
new file mode 100644
index 0000000..e6ce596
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png
new file mode 100644
index 0000000..2a9fc21
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png
new file mode 100644
index 0000000..42cad5e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png
new file mode 100644
index 0000000..0612b25
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png
new file mode 100644
index 0000000..aaa3d0f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png
new file mode 100644
index 0000000..66b3e9d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png
new file mode 100644
index 0000000..5fbd723
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png
new file mode 100644
index 0000000..74b7431
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png
new file mode 100644
index 0000000..2945fbd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png
new file mode 100644
index 0000000..9dde7da
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png
new file mode 100644
index 0000000..8afbb6d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png
new file mode 100644
index 0000000..209df49
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png
new file mode 100644
index 0000000..3dbcc48
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png
new file mode 100644
index 0000000..4014860
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png
new file mode 100644
index 0000000..1a6f577
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png
new file mode 100644
index 0000000..30f0db3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png
new file mode 100644
index 0000000..d0729da
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png
new file mode 100644
index 0000000..6cbd1f4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png
new file mode 100644
index 0000000..b6af5e7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png
new file mode 100644
index 0000000..eca7a46
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png
new file mode 100644
index 0000000..3511d52
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png
new file mode 100644
index 0000000..21ad59f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png
new file mode 100644
index 0000000..471d78c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png
new file mode 100644
index 0000000..6be9e6b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png
new file mode 100644
index 0000000..0b9a077
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png
new file mode 100644
index 0000000..71075a7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png
new file mode 100644
index 0000000..6aabc3c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png
new file mode 100644
index 0000000..a2045e1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png
new file mode 100644
index 0000000..1f4d161
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png
new file mode 100644
index 0000000..85b0634
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png
new file mode 100644
index 0000000..52e29fc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png
new file mode 100644
index 0000000..103a2c3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png
new file mode 100644
index 0000000..4e76add
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png
new file mode 100644
index 0000000..b1a39e1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png
new file mode 100644
index 0000000..052f551
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png
new file mode 100644
index 0000000..b0020f2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png
new file mode 100644
index 0000000..32139ce
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png b/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png
new file mode 100644
index 0000000..f666309
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png
new file mode 100644
index 0000000..7c12096
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png
new file mode 100644
index 0000000..4cef095
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png
new file mode 100644
index 0000000..5ab38fd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png
new file mode 100644
index 0000000..c40ce17
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png b/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png
new file mode 100644
index 0000000..48a23f6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png
new file mode 100644
index 0000000..d8b02e0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png
new file mode 100644
index 0000000..807f2c1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_call_mute.png b/core/res/res/drawable-xxhdpi/stat_notify_call_mute.png
new file mode 100644
index 0000000..54fc740
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png b/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
new file mode 100755
index 0000000..b01e00f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_chat.png b/core/res/res/drawable-xxhdpi/stat_notify_chat.png
new file mode 100644
index 0000000..960fdd4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_disabled.png b/core/res/res/drawable-xxhdpi/stat_notify_disabled.png
new file mode 100644
index 0000000..06d7677b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png b/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
new file mode 100755
index 0000000..cd790a6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png b/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
new file mode 100755
index 0000000..ba98c67
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_error.png b/core/res/res/drawable-xxhdpi/stat_notify_error.png
new file mode 100644
index 0000000..fa5f7a3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_gmail.png b/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
new file mode 100755
index 0000000..4640e88
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png b/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png
new file mode 100644
index 0000000..904df3b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_more.png b/core/res/res/drawable-xxhdpi/stat_notify_more.png
new file mode 100755
index 0000000..f3a46ec
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
new file mode 100644
index 0000000..86c34ed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
new file mode 100755
index 0000000..87e9d20
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
new file mode 100755
index 0000000..735ccc9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
new file mode 100755
index 0000000..e7512ed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
new file mode 100755
index 0000000..d1cf3d7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync.png b/core/res/res/drawable-xxhdpi/stat_notify_sync.png
new file mode 100755
index 0000000..2a36702
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
new file mode 100755
index 0000000..2a36702
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
new file mode 100755
index 0000000..db2f0e2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png b/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
new file mode 100755
index 0000000..71dfe68
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-xxhdpi/stat_notify_wifi_in_range.png
new file mode 100644
index 0000000..47e74fb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png b/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png
new file mode 100644
index 0000000..0820f07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
new file mode 100755
index 0000000..6dd4d7f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png b/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
new file mode 100755
index 0000000..7fcf5cd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
new file mode 100644
index 0000000..aeccbd6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
new file mode 100644
index 0000000..3cdc45d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
new file mode 100755
index 0000000..836db12
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
new file mode 100755
index 0000000..5bc3add4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
new file mode 100755
index 0000000..962c450
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
new file mode 100755
index 0000000..e1d0d55
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
new file mode 100755
index 0000000..84420de
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
new file mode 100755
index 0000000..b495943
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
new file mode 100755
index 0000000..81fb04a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png b/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..9348384
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_secure.png b/core/res/res/drawable-xxhdpi/stat_sys_secure.png
new file mode 100755
index 0000000..07c27cb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_speakerphone.png b/core/res/res/drawable-xxhdpi/stat_sys_speakerphone.png
new file mode 100644
index 0000000..40d1a35
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png b/core/res/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
new file mode 100644
index 0000000..25acfbb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_general.png b/core/res/res/drawable-xxhdpi/stat_sys_tether_general.png
new file mode 100644
index 0000000..5c65601
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_tether_general.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_usb.png b/core/res/res/drawable-xxhdpi/stat_sys_tether_usb.png
new file mode 100644
index 0000000..28b4b54
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_tether_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-xxhdpi/stat_sys_tether_wifi.png
new file mode 100644
index 0000000..da44e6a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_tether_wifi.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_throttled.png b/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
new file mode 100755
index 0000000..c2189e4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
new file mode 100755
index 0000000..9e63fca
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
new file mode 100755
index 0000000..39dd3b8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
new file mode 100755
index 0000000..b828430
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
new file mode 100755
index 0000000..7834460
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
new file mode 100755
index 0000000..34c6f27
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
new file mode 100755
index 0000000..1270acf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_warning.png b/core/res/res/drawable-xxhdpi/stat_sys_warning.png
new file mode 100755
index 0000000..907de0f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png
new file mode 100644
index 0000000..e80453e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png
new file mode 100644
index 0000000..0ec08ee
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png
new file mode 100644
index 0000000..13f852d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png
new file mode 100644
index 0000000..e7767b8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png
new file mode 100644
index 0000000..d1133bf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png
new file mode 100644
index 0000000..4532035
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png
new file mode 100644
index 0000000..2b3e151
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png
new file mode 100644
index 0000000..77c08a5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png
new file mode 100644
index 0000000..5f36c04
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png
new file mode 100644
index 0000000..7c16463
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png
new file mode 100644
index 0000000..f14f0d6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png
new file mode 100644
index 0000000..9920f54
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png
new file mode 100644
index 0000000..00518ad
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png
new file mode 100644
index 0000000..bdcfc74
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png
new file mode 100644
index 0000000..302b4e2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_def_app_icon.png b/core/res/res/drawable-xxhdpi/sym_def_app_icon.png
new file mode 100644
index 0000000..20a47a0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png b/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png
new file mode 100644
index 0000000..9230135
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png b/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png
new file mode 100644
index 0000000..a234cde
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png
new file mode 100644
index 0000000..da434a4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png
new file mode 100644
index 0000000..715e9aee
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png
new file mode 100644
index 0000000..d0cbce2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png
new file mode 100644
index 0000000..d152442
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png
new file mode 100644
index 0000000..9438f47
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png
new file mode 100644
index 0000000..0104cfe
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png
new file mode 100644
index 0000000..852d0a22
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png
new file mode 100644
index 0000000..bdd1e22
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png
new file mode 100644
index 0000000..0d9a0f3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png
new file mode 100644
index 0000000..ab87892
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png
new file mode 100644
index 0000000..7d95807
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..619efa4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png b/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..bee35ca
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..8987d99
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..e9a5bf5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png b/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..8fcecf7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..92419c49
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png b/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png
new file mode 100644
index 0000000..9e247e6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png b/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png
new file mode 100644
index 0000000..9e247e6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left.png b/core/res/res/drawable-xxhdpi/text_select_handle_left.png
new file mode 100644
index 0000000..8497601
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_middle.png b/core/res/res/drawable-xxhdpi/text_select_handle_middle.png
new file mode 100644
index 0000000..7b74f66
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right.png b/core/res/res/drawable-xxhdpi/text_select_handle_right.png
new file mode 100644
index 0000000..25e07806
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png
new file mode 100644
index 0000000..a4c891e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png
new file mode 100644
index 0000000..a4c891e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png
new file mode 100644
index 0000000..1e8dafa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png
new file mode 100644
index 0000000..9ece814
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..e21548e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..5bc20f9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png
new file mode 100644
index 0000000..5592f76
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png
new file mode 100644
index 0000000..8fda94d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png
new file mode 100644
index 0000000..d557164
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png
new file mode 100644
index 0000000..d557164
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png
new file mode 100644
index 0000000..a4c891e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png
new file mode 100644
index 0000000..a4c891e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png
new file mode 100644
index 0000000..1e8dafa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png
new file mode 100644
index 0000000..9ece814
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..e21548e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..5bc20f9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png
new file mode 100644
index 0000000..5592f76
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png
new file mode 100644
index 0000000..8fda94d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png
new file mode 100644
index 0000000..d557164
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png
new file mode 100644
index 0000000..d557164
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png
new file mode 100644
index 0000000..e634c750
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png
new file mode 100644
index 0000000..ea9dd89
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png
new file mode 100644
index 0000000..6042bcf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png
new file mode 100644
index 0000000..b34b536
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png
new file mode 100644
index 0000000..114acf4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png
new file mode 100644
index 0000000..098475b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png
new file mode 100644
index 0000000..8fcaadc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png
new file mode 100644
index 0000000..df5c730
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/toast_frame.9.png b/core/res/res/drawable-xxhdpi/toast_frame.9.png
new file mode 100644
index 0000000..882b9c6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/toast_frame_holo.9.png b/core/res/res/drawable-xxhdpi/toast_frame_holo.9.png
new file mode 100644
index 0000000..882b9c6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..a5dc6cb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/vpn_connected.png b/core/res/res/drawable-xxhdpi/vpn_connected.png
new file mode 100644
index 0000000..ea4930c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/vpn_connected.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/vpn_disconnected.png b/core/res/res/drawable-xxhdpi/vpn_disconnected.png
new file mode 100644
index 0000000..4cd0dd4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable/spinner_ab_holo_dark.xml b/core/res/res/drawable/spinner_ab_holo_dark.xml
index 0932eff..9b8967c 100644
--- a/core/res/res/drawable/spinner_ab_holo_dark.xml
+++ b/core/res/res/drawable/spinner_ab_holo_dark.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:autoMirrored="true">
     <item android:state_enabled="false"
           android:drawable="@drawable/spinner_ab_disabled_holo_dark" />
     <item android:state_pressed="true"
diff --git a/core/res/res/drawable/spinner_ab_holo_light.xml b/core/res/res/drawable/spinner_ab_holo_light.xml
index e785cf4..a324c08 100644
--- a/core/res/res/drawable/spinner_ab_holo_light.xml
+++ b/core/res/res/drawable/spinner_ab_holo_light.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:autoMirrored="true">
     <item android:state_enabled="false"
           android:drawable="@drawable/spinner_ab_disabled_holo_light" />
     <item android:state_pressed="true"
diff --git a/core/res/res/drawable/spinner_background_holo_dark.xml b/core/res/res/drawable/spinner_background_holo_dark.xml
index eb6b18b..a57f720 100644
--- a/core/res/res/drawable/spinner_background_holo_dark.xml
+++ b/core/res/res/drawable/spinner_background_holo_dark.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:autoMirrored="true">
     <item android:state_enabled="false"
           android:drawable="@drawable/spinner_disabled_holo_dark" />
     <item android:state_pressed="true"
diff --git a/core/res/res/drawable/spinner_background_holo_light.xml b/core/res/res/drawable/spinner_background_holo_light.xml
index 9d17ed0c..899633c 100644
--- a/core/res/res/drawable/spinner_background_holo_light.xml
+++ b/core/res/res/drawable/spinner_background_holo_light.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:autoMirrored="true">
     <item android:state_enabled="false"
           android:drawable="@drawable/spinner_disabled_holo_light" />
     <item android:state_pressed="true"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index fbeb5b1..a21aaad 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Laat die program toe om uit die stelsel se verskeie loglêers te lees. Dit laat \'n program toe om algemene inligting te ontdek oor wat jy met die foon doen, wat moontlik persoonlike of private inligting kan insluit."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"gebruik enige mediadekodeerder vir terugspeel"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Laat die program toe om enige geïnstalleer mediadekodeerder te gebruik om te kan dekodeer vir terugspeel."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"bestuur vertroude eiebewyse"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Laat die program CA-sertifikate as vertroude eiebewyse installeer en deïnstalleer."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lees/skryf na bronne wat diag besit"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Laat die program toe om na enige hulpbron wat deur die diag-groep besit word, te skryf, byvoorbeeld lêers in /dev. Dit kan potensieel stelselstabiliteit en sekuriteit affekteer. Dit moet NET gebruik word vir hardewarespesifieke diagnose deur die vervaardiger of operateur."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktiveer of deaktiveer programkomponente"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index aaeb2d6..50e4fd0 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">" ከስርዓቱ የተለያዩ የማስታወሻ ፋይሎች ውስጥ ለማንበብ ለመተግበሪያይፈቅዳሉ። ይህ ስለ ስልክህ ምን እያደረክበት እንደሆነ የግላዊ  ወይም የግል መረጃን ጨምሮ ጠቅላላ መረጃ ለማግኘት ይፈቅዳል።"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"ለመልሰህ አጫውት ማንኛውምንም የማህደረ መረጃ ዲኮደር ተጠቀም"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"ለመልሰህ አጫውት ፍታን በማንኛውም የተጫኑ በማህደረ መረጃ ዲኮደር ለመጠቀም  ለመተግበሪያ ይፈቅዳል።"</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"የታመኑ ምስክርነቶችን ያስተዳድሩ"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"መተግበሪያው CA የምስክር ወረቀቶችን እንደሚታመኑ ምስክርነቶች አንዲጭን እና እንዲያራግፍ ይፍቀዱ።"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"በdiag ባለቤትነት ያሉ ንብረቶችን አንብብ/ፃፍ"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"በዲያግ ቡድን ባለቤትነት ወደ አለ ማንኛውም ንብረት ለምሳሌ በ/dev ያሉ ፋይሎች ለማንበብ እና ለመፃፍ ለመተግበሪያው ይፈቅዳሉ። ይህ በመሰረቱ የስርዓት መረጋጋትን እና ደህንነትን ሊጎዳ ይችላል። ይህ ውስን የሀርድዌር-ተኮር ዲያግኖስቲክስ በአምራቹ ወይም ከዋኙ ብቻ መሆን አለበት።"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"የመተግበሪያ ምንዝሮችን አንቃ ወይም አቦዝን"</string>
@@ -1579,6 +1581,6 @@
     <item quantity="one" msgid="4835639969503729874">"ትክክል ያልሆነ ፒን። በ1 ሰከንድ ውስጥ እንደገና ይሞክሩ።"</item>
     <item quantity="other" msgid="8030607343223287654">"ትክክል ያልሆነ ፒን። በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ።"</item>
   </plurals>
-    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"አሞሌውን ለማሳየት የማያ ገጹን ጠርዝ ላይ ያንሸራትቱ"</string>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"አሞሌውን ለማሳየት የማያ ገጹ ጠርዝ ላይ ያንሸራትቱ"</string>
     <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"አሞሌውን ለማሳየት ከማያ ገጹ ጠርዝ ጀምረው ያንሸራትቱ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 172b36e..50c038f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"للسماح للتطبيق بالقراءة من ملفات سجلات النظام المتنوعة. ويسمح ذلك للتطبيق باكتشاف المعلومات العامة حول ما تفعله بالهاتف، ومن المحتمل أن يتضمن معلومات شخصية أو خاصة."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"استخدام أي برنامج فك تشفير وسائط من أجل التشغيل"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"السماح للتطبيق باستخدام أي برنامج فك تشفير وسائط مثبت لفك التشفير من أجل التشغيل."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"قراءة/كتابة إلى الموارد المملوكة بواسطة التشخيص"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"للسماح للتطبيق بالقراءة والكتابة إلى أي مورد مملوك بواسطة مجموعة التشخيصات؛ على سبيل المثال، الملفات في /dev. من المحتمل أن يؤثر ذلك في استقرار النظام وأمانه. يجب ألا يستخدم ذلك سوى للتشخيصات الخاصة بالنظام من قِبل المصنِّع أو المشغِّل."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"تمكين مكونات التطبيق أو تعطيلها"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index b6bd753..08e79bb 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Tətbiqə sistemin müxtəlif jurnal fayllarını oxumağa imkan verir. Bu da Sizin planşetdə etdikləriniz haqqında məlumatlar, həmçinin şəxsi və konfidensial məlumatlar ola bilər."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"oxutmaq üçün istənilən media dekoderi istifadə edir"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Tətbiqə playback\'i deşifrə etmək üçün hər hansı bir quraşdırılmış media deşifrələyicisini istifadə etmık imkanı verir."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"etibarlı etimadnamələri idarə et"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Tətbiqə etibarlı etimadnamələr kimi CA sertifikatlarını quraşdırmaq və sistemdən silməyə icazə verir."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"diaga məxsus olan mənbələri yaz/oxu"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Tətbiqə diag qrupa məsus olan resursları yazmaq və oxumaq icazəsi verir; məsələn  /dev qovluğundakı fayllar. Bu sistemin stabilliyinə və təhlükəsizliyinə təsir edə bilər. Bu ancaq istehsalçı və ya operator tərəfindən avadanlığa xas diaqnostika üçün olmalıdır."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"tətbiq komponentlərini aktivləşdirmə və ya deaktivləşdirmə"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 72d6483..3d0b851 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -418,6 +418,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Дазваляе прыкладанню счытваць розныя сістэмныя файлы гiсторый. Гэта дазваляе атрымліваць агульную інфармацыю аб тым, як выкарыстоўваецца тэлефон, у тым ліку, магчыма, асабістую або прыватную інфармацыю."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"для прайгравання выкарыстоўваць любы мультымедыйны дэкодэр"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Дазваляе прыкладанням выкарыстоўваць любы ўсталяваны iнструмент для мультымедыйнага дэкадавання, каб прайграць."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"чытаць/запісваць на дыягнастычныя рэсурсы"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Дазваляе прыкладанням счытваць і запісваць любы рэсурс, які належыць дыягнастычнай групе, напрыклад файлы распрацоўшчыка ў тэчцы /dev. Патэнцыйна гэта можа паўплываць на стабільнасць і бяспеку сістэмы. Гэта павінна выкарыстоўвацца ТОЛЬКІ для апаратнай дыягностыкі вытворцам або аператарам."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"уключыць або адключыць кампаненты прыкладання"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 1b437f5..d5d1827 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Разрешава на приложението да чете от различните регистрационни файлове на системата. Това му позволява да получи обща информация какво правите с телефона, потенциално включително и лични или поверителни данни."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"използване на всеки медиен декодер за възпроизвеждане"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Разрешава на приложението да използва всеки инсталиран медиен декодер с цел декодиране за възпроизвеждане."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"четене/запис в ресурси, притежавани от diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Разрешава на приложението да чете и записва във всеки ресурс, притежаван от групата diag, например файловете в /dev. Това потенциално може да засегне стабилността и сигурността на системата. То трябва да се използва САМО за диагностика, конкретно за хардуера, от страна на производителя или оператора."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"активиране или деактивиране на компоненти на приложенията"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index dd55df5..5c257ca 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permet que l\'aplicació llegeixi els diversos fitxers de registre del sistema. Això li permet descobrir informació general sobre què estàs fent amb el telèfon i, potencialment, pot incloure informació personal o privada."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"utilitza qualsevol descodificador de mitjans per a la reproducció"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permet que l\'aplicació utilitzi qualsevol descodificador de mitjans instal·lat per descodificar per a la reproducció."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"llegir/escriure recursos propietat de diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permet que l\'aplicació llegeixi i escrigui a qualsevol recurs propietat del grup diag; per exemple, els fitxers de /dev. Això podria afectar l\'estabilitat i la seguretat del sistema. NOMÉS l\'hauria d\'utilitzar el fabricant o l\'operador per a diagnòstics específics de maquinari."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"activa o desactiva els components de l\'aplicació"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 55d45da..3a4009b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Umožňuje aplikaci číst různé systémové soubory protokolů. Toto oprávnění aplikaci umožní získat obecné informace o činnostech s telefonem, které by mohly obsahovat osobní či soukromé informace."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"použít jakýkoliv dekodér pro přehrávání médií"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Umožňuje aplikaci používat libovolný nainstalovaný dekodér médií k dekódování při přehrávání."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"čtení nebo zápis do prostředků funkce diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Umožňuje aplikaci číst libovolné prostředky ve skupině diag, např. soubory ve složce /dev, a zapisovat do nich. Může dojít k ovlivnění stability a bezpečnosti systému. Toto nastavení by měl používat POUZE výrobce či operátor pro diagnostiku hardwaru."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktivace či deaktivace komponent aplikací"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f8e6e7c..508d3c6 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Tillader, at appen kan læse i systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med telefonen registreres, også personlige eller private oplysninger."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"brug enhver mediedekoder til afspilning"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Tillader, at appen bruger enhver installeret medieafkoder til at afkode til afspilning."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"læs/skriv til ressourcer ejet af diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Tillader, at appen kan læse og skrive til alle ressourcer, der ejes af diag-gruppen,  f.eks. filer i /dev. Dette kan muligvis påvirke systemets stabilitet og sikkerhed. Dette bør KUN bruges til hardwarespecifik diagnosticering, som foretages af producenten eller udbyderen."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktivere eller deaktivere appkomponenter"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1c67f7f..6fae411 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Ermöglicht der App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden, darunter auch personenbezogene oder vertrauliche Daten."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Für Wiedergabe beliebigen Mediendecodierer verwenden"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Ermöglicht der App, alle installierten Mediendecodierer zur Wiedergabe zu verwenden."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"Vertrauenswürdige Anmeldedaten verwalten"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Ermöglicht der App, CA-Zertifikate als vertrauenswürdige Anmeldedaten zu installieren und zu deinstallieren."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Lese-/Schreibberechtigung für zu Diagnosegruppe gehörige Elemente"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Ermöglicht der App, alle Elemente in der Diagnosegruppe zu lesen und zu bearbeiten, etwa Dateien in \"/dev\". Dies könnte eine potenzielle Gefährdung für die Stabilität und Sicherheit des Systems darstellen und sollte NUR für hardwarespezifische Diagnosen des Herstellers oder Mobilfunkanbieters verwendet werden."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"App-Komponenten aktivieren oder deaktivieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a01ef71..935bf45 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Επιτρέπει στην εφαρμογή την ανάγνωση των αρχείων καταγραφής του συστήματος. Έτσι, μπορεί να ανακαλύψει γενικές πληροφορίες σχετικά με τις δραστηριότητές σας στο τηλέφωνο, συμπεριλαμβάνοντας πιθανώς και προσωπικές ή ιδιωτικές πληροφορίες."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"χρήση οποιουδήποτε αποκωδικοποιητή μέσων για αναπαραγωγή"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Επιτρέπει στην εφαρμογή τη χρήση οποιουδήποτε εγκατεστημένου αποκωδικοποιητή μέσων για αναπαραγωγή."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"διαχείριση αξιόπιστων διαπιστευτηρίων"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Επιτρέπει στην εφαρμογή την εγκατάσταση και την απεγκατάσταση πιστοποιητικών CA ως αξιόπιστων διαπιστευτηρίων."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ανάγνωση/εγγραφή σε πόρους που ανήκουν στο διαγνωστικό"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Επιτρέπει στην εφαρμογή την ανάγνωση και την εγγραφή σε οποιονδήποτε πόρο που ανήκει στην ομάδα διαγνωστικού (π.χ. αρχεία στον κατάλογο /dev). Αυτό ενδέχεται να επηρεάσει την σταθερότητα και την ασφάλεια του συστήματος. Θα πρέπει να χρησιμοποιείται ΜΟΝΟ για διαγνωστικά υλικού από τον κατασκευαστή ή τον χειριστή."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"ενεργοποίηση ή απενεργοποίηση στοιχείων εφαρμογής"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8a3f354..2e913e7 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Allows the app to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"use any media decoder for playback"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Allows the app to use any installed media decoder to decode for playback."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"manage trusted credentials"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Allows the app to install and uninstall CA certificates as trusted credentials."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"read/write to resources owned by diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Allows the app to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"enable or disable app components"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8a3f354..2e913e7 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Allows the app to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"use any media decoder for playback"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Allows the app to use any installed media decoder to decode for playback."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"manage trusted credentials"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Allows the app to install and uninstall CA certificates as trusted credentials."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"read/write to resources owned by diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Allows the app to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"enable or disable app components"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 983bfb3..9d56290 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permite que la aplicación lea los diversos archivos de registro del sistema. Esto le permite descubrir información general acerca de lo que haces con el dispositivo, que puede incluir información personal o privada."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Usar cualquier decodificador de medios para la reproducción"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permite que la aplicación use cualquier decodificador de archivos multimedia instalado para la reproducción."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"leer y escribir a recursos dentro del grupo de diagnóstico"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permite que la aplicación lea y escriba en cualquier recurso propiedad del grupo de diagnóstico como, por ejemplo, archivos in/dev. Este permiso podría afectar la seguridad y estabilidad del sistema. SOLO se debe utilizar para diagnósticos específicos de hardware realizados por el fabricante o el operador."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"activar o desactivar componentes de la aplicación"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index fa38dbc5c..b1bc337 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permite que la aplicación consulte distintos archivos de registro del sistema. La aplicación puede usar este permiso para obtener información general sobre las acciones que realizas con el dispositivo, que puede incluir datos personales o privados."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Utilizar cualquier decodificador de archivos multimedia para la reproducción"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permite que la aplicación use cualquier decodificador de archivos multimedia instalado para la reproducción."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"leer/escribir en los recursos propiedad del grupo de diagnóstico"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permite que la aplicación consulte y escriba en cualquier recurso del grupo de diagnóstico como, por ejemplo, archivos en /dev. Este permiso podría afectar a la seguridad y estabilidad del sistema. SOLO se debe usar para diagnósticos específicos de hardware realizados por el fabricante o el operador."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"habilitar o inhabilitar componentes de la aplicación"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index df92621..0694744 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Võimaldab rakendusel lugeda süsteemi erinevaid logifaile. Nii on võimalik avastada üldist teavet selle kohta, mida te telefoniga teete, mis võib kaasata ka isiklikku või privaatset teavet."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Mis tahes meediumidekooderi kasutamine taasesituseks"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Võimaldab rakendusel taasesituseks kasutada mis tahes installitud meediumidekooderit."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"loe/kirjuta valija allikaid"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Võimaldab rakendusel lugeda valimisrühma mis tahes ressurssi ja sellesse kirjutada (näiteks kaustas /dev olevad failid). See võib mõjutada süsteemi stabiilsust ja turvet. Seda tohiks kasutada tootja või operaator AINULT riistvaraspetsiifiliseks diagnostikaks."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"Rakenduse komponentide lubamine või keelamine"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 8f12064..71988f7 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"به برنامه اجازه می‎دهد تا فایل‌های گزارش مختلف سیستم را بخواند. این کار به برنامه اجازه می‎دهد اطلاعات عمومی کاری که با تلفن انجام می‎دهید مثلا اطلاعات خصوصی و شخصی را کشف کند."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"استفاده از هر رمزگشای رسانه‎ای برای بازپخش"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"اجازه می‎دهد برنامه از هر رمزگشای رسانه نصب شده‌ای استفاده کند تا برای پخش رمزگشایی شود."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"خواندن/نوشتن منابع متعلق به تشخیص"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"به برنامه اجازه می‌دهد هر منبعی را که متعلق به گروه تشخیص است بخواند و در آن بنویسد؛ به‌عنوان مثال، فایل‌های /dev. این امر به‌صورت بالقوه می‌تواند بر پایدار بودن و امنیت سیستم تأثیر بگذارد. این تنها باید برای تشخیص‎‌های مختص سخت‌افزار توسط تولیدکننده یا اپراتور استفاده شود."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"فعال یا غیر فعال کردن اجزای برنامه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ee990b8..c8f2c2f 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Antaa sovelluksen lukea järjestelmän lokitiedostoja. Näin sovellus saa yleisiä tietoja siitä, mitä teet puhelimella, sekä mahdollisia yksityisiä tai arkaluonteisia tietoja."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"käytä mitä tahansa tietovälineen koodin purkajaa toistoa varten"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Sallii sovelluksen käyttää mitä tahansa asennettua tietovälineen koodin purkajaa toistoa varten."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"hallinnoi luotettavia varmenteita"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Antaa sovellukselle luvan asentaa ja poistaa luotettavia CA-varmenteita."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lue diag:in omistamia resursseja / kirjoita resursseihin"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Antaa sovelluksen lukea ja kirjoittaa diag-ryhmän omistamiin resursseihin, esimerkiksi /dev-hakemistossa oleviin tiedostoihin. Tämä voi vaikuttaa järjestelmän vakauteen ja turvallisuuteen. Tämä lupa tulee myöntää VAIN valmistajan tai operaattorin laitteistotesteille."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"sovelluskomponenttien ottaminen käyttöön tai pois käytöstä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d3792e7..86aea80 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permet à l\'application de lire les différents fichiers journaux du système afin d\'obtenir des informations générales sur la façon dont vous utilisez votre téléphone. Celles-ci peuvent éventuellement inclure des informations d\'ordre personnel ou privé."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"utiliser n\'importe quel décodeur pour lire les fichiers multimédias"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permet à une application d\'utiliser n\'importe quel décodeur installé pour lire les fichiers multimédias."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lire ou modifier les ressources appartenant au groupe de diagnostics"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permet à l\'application d\'obtenir des droits en lecture et en écriture pour toute ressource appartenant au groupe de diagnostics (par exemple, les fichiers du répertoire /dev). Cela peut affecter la stabilité et la sécurité du système. Cette fonctionnalité est UNIQUEMENT réservée aux diagnostics matériels effectués par le fabricant ou le fournisseur de services."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"activer ou désactiver les composants d\'une application"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 763fbac..d9ecdf9 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permet à l\'application de lire les différents fichiers journaux du système afin d\'obtenir des informations générales sur la façon dont vous utilisez votre téléphone. Celles-ci peuvent éventuellement inclure des informations d\'ordre personnel ou privé."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"utiliser n\'importe quel décodeur pour lire les fichiers multimédias"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permet à une application d\'utiliser n\'importe quel décodeur installé pour lire les fichiers multimédias."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Lecture/écriture dans les ressources appartenant aux diagnostics"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permet à l\'application d\'obtenir des droits en lecture/écriture concernant toute ressource appartenant au groupe de diagnostics (par exemple, les fichiers du répertoire /dev). Ceci peut affecter la stabilité et la sécurité du système. Cette fonctionnalité est UNIQUEMENT réservée aux diagnostics matériels effectués par le fabricant ou l\'opérateur."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"activer ou désactiver les composants de l\'application"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9b4d892..8c6ead8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"एप्‍लिकेशन को सिस्‍टम की विभिन्‍न लॉग फ़ाइलें पढ़ने देता है. संभावित रूप से व्यक्तिगत या निजी जानकारी सहित, यह इसे इस बारे में सामान्य जानकारी खोजने देता है कि आप फ़ोन से क्‍या कर रहे हैं."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"प्लेबैक के लिए किसी भी मीडिया डीकोडर का उपयोग करें"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"एप्लिकेशन को प्लेबैक डीकोड करने के लिए किसी भी इंस्टॉल किए गए डीकोडर का उपयोग करने देता है."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"विश्वसनीय क्रेडेंशियल प्रबंधित करें"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"एप्लिकेशन को CA प्रमाणपत्रों को विश्वसनीय क्रेडेंशियल के रूप में इंस्टॉल और अनइंस्टॉल करने दें"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"निदान के स्‍वामित्‍व वाले संसाधनों को पढ़ें/लिखें"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"एप्‍लिकेशन को diag समूह के स्‍वामित्‍व वाले किसी संसाधन को पढ़ने और उसमें लिखने देता है; उदाहरण के लिए, /dev की फ़ाइलें. यह सिस्‍टम की स्‍थिरता और सुरक्षा को संभावित रूप से प्रभावित कर सकता है. इसका उपयोग निर्माता या ऑपरेटर द्वारा केवल हार्डवेयर-विशिष्ट निदान के लिए किया जाना चाहिए."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"एप्‍लिकेशन घटकों को सक्षम या अक्षम करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f9a6fec..e54394b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Aplikaciji omogućuje čitanje raznih sistemskih datoteka zapisnika. Tako može otkriti opće informacije o tome što radite na telefonu, što potencijalno uključuje osobne ili privatne informacije."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"upotrijebi bilo koji dekoder za reprodukciju"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Aplikaciji omogućuje korištenje bilo kojim instaliranim dekoderom medija za dekodiranje radi reprodukcije."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"pisanje/čitanje u resursima čije je vlasnik dijagnostika"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Aplikaciji omogućuje čitanje i pisanje na bilo koji resurs u vlasništvu dijag. grupe; na primjer, datoteke u sustavu /dev. To bi moglo utjecati na stabilnost sustava i sigurnost. Dozvolu bi trebao upotrebljavati proizvođač ili operater SAMO za dijagnostiku koja se odnosi na hardver."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"omogućavanje ili onemogućavanje komponenti aplikacije"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b8aca5c..8f5dabf 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Lehetővé teszi az alkalmazás számára, hogy olvassa a rendszer különböző naplófájljait. Ezáltal általános információkat deríthet ki arról, hogy mire használja a telefonját, valamint személyes, magánjellegű adatokhoz is hozzájuthat."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"bármely médiadekóder használata lejátszáshoz"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Lehetővé teszi egy alkalmazás számára bármely telepített médiadekóder használatát a lejátszás dekódolásához."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"megbízható tanúsítványok kezelése"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Lehetővé teszi az alkalmazás számára a CA tanúsítványok telepítését és eltávolítását."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"a diag tulajdonában lévő erőforrások olvasása és írása"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Lehetővé teszi egy alkalmazás számára, hogy olvassa és írja a diagnosztikai csoport minden erőforrását, például a /dev könyvtárban lévő fájlokat. Ez potenciálisan befolyásolhatja a rendszer stabilitását és biztonságát, ezért CSAK a gyártó vagy a szolgáltató használhatja hardverspecifikus diagnosztizálásra."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"alkalmazáskomponensek be- és kikapcsolása"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index fd50852..60c5c55 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Թույլ է տալիս հավելվածին կարդալ համակարգի տարբեր գրանցամատյանային ֆայլերից: Սա թույլ է տալիս ստանալ ընդհանուր տեղեկություններ այն մասին, թե ինչ եք անում հեռախոսով, այդ թվում` անձնական կամ գաղտնի տեղեկություններ:"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"օգտագործել ցանկացած մեդիա վերծանիչ նվագարկման համար"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Թույլ է տալիս հավելվածին օգտագործել ցանկացած տեղադրված մեդիա վերծանիչ` նվագարկումը ապակոդավորելու համար:"</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"կառավարեք վստահելի վկայագրերը"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Թույլատրում է հավելվածին տեղադրել և ապատեղադրել CA վկայագրերը՝ որպես վստահելի:"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"կարդալ կամ գրել ախտորոշիչին պատկանող ռեսուրսները"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Թույլ է տալիս հավելվածին կարդալ և գրել ախտորոշիչ խմբին պատկանող ցանկացած ռեսուրսում, ինչպես օրինակ ֆայլերը /dev-ում: Դա կարող է ազդել համակարգի կայունության և անվտանգության վրա: Սա պետք է օգտագործել միայն արտադրողի կամ օպերատորի կողմից սարքին հատուկ ախտորոշման համար:"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"միացնել կամ անջատել հավելվածի բաղադրիչները"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5194ac8..9db1d1c 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Mengizinkan apl membaca dari berbagai file log sistem. Izin ini memungkinkan apl menemukan informasi umum tentang hal-hal yang Anda lakukan di ponsel, kemungkinan termasuk informasi pribadi."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"menggunakan media pengawasandi apa pun untuk pemutaran"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Mengizinkan apl menggunakan pengawasandi media apa pun yang terpasang guna mengawasandikan media untuk diputar."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber daya yang dimiliki oleh diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, file dalam /dev. Izin ini berpotensi memengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnosis khusus perangkat keras oleh pabrikan atau operator."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"mengaktifkan atau menonaktifkan komponen apl"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index dfac858..18d0210 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Consente all\'applicazione di leggere vari file di registro del sistema per trovare informazioni generali sulle operazioni effettuate con il telefono. Tali file potrebbero contenere informazioni personali o riservate."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"uso di qualsiasi decoder multimediale per la riproduzione"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Consente all\'applicazione di utilizzare qualsiasi decoder multimediale installato per la decodifica ai fini della riproduzione."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"gestione di credenziali attendibili"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Consente all\'app di installare e disinstallare certificati CA come credenziali attendibili."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lettura/scrittura risorse di proprietà di diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Consente all\'applicazione di leggere le risorse del gruppo diag e scrivere in esse, ad esempio i file in /dev. Ciò potrebbe influire su stabilità e sicurezza del sistema. Dovrebbe essere utilizzata SOLTANTO per diagnostiche specifiche dell\'hardware effettuate dal produttore o dall\'operatore."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"attivazione/disattivazione componenti applicazioni"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9bc828e..2b80541 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"מאפשר ליישום לקרוא מקובצי היומן השונים של המערכת. כך מתאפשר ליישום לגלות מידע כללי על הפעולות שלך בטלפון, מידע שעשוי לכלול מידע אישי או פרטי."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"שימוש בכל מפענח מדיה שהוא להפעלה"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"הרשאה זו מאפשרת ליישום להשתמש בכל מפענח מדיה מותקן כדי לבצע פענוח להשמעה."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"ניהול פרטי כניסה מהימנים"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"מאפשרת לאפליקציה להתקין ולהסיר אישורי CA כפרטי כניסה מהימנים."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"קרא/כתוב במשאבים בבעלות diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"מאפשר ליישום לקרוא ולכתוב בכל משאב שבבעלות קבוצת ה-diag; לדוגמה, קבצים ב-‎/dev. פעולה זו עשויה להשפיע על היציבות והאבטחה של המערכת. אפשרות זו צריכה לשמש רק את היצרן או המפעיל, לצורך אבחונים ספציפיים לחומרה."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"הפעלה או השבתה של רכיבי יישומים"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3a3d1e8..4744135 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"システムの各種ログファイルの読み取りをアプリに許可します。許可すると、アプリでは携帯端末の使用に関する全般的な情報を読み取れるようになります。この情報には個人情報や機密情報が含まれる場合があります。"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"再生用にメディア デコーダーを使用"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"インストール済みのメディアデコーダーを使用して再生用にデコードすることをアプリに許可します。"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"diagが所有するリソースの読み書き"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"diagグループが所有するリソース(/dev内のファイルなど)の読み書きをアプリに許可します。許可すると、システムの安定性とセキュリティに影響が生じる可能性があります。メーカー/通信事業者によるハードウェア固有の診断以外には使用しないでください。"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"アプリのコンポーネントの有効/無効化"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a72ebad..94fb8d0 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"აპს შეეძლება სისტემის სხვადასხვა ჟურნალის ფაილების წაკითხვა. ეს უფლებას აძლევს, გაიგოს ზოგადი ინფორმაცია იმის შესახებ, თუ რას აკეთებთ ტელეფონზე და, პოტენციურად, პირადი ან კონფიდენციალური ინფორმაციაც."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"ნებისმიერი მედია დეკოდერის გამოყენება"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"აპს დასაკრავად შეეძლება გამოიყენოს ნებისმიერი დაყენებული მედია დეკოდერი."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"სისტემის დიაგნოსტიკის რესურსებში წაკითხვა/ჩაწერის უფლება"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"აპს შეეძლება, წაიკითხოს ან ჩაწეროს ნებისმიერ რესურსში, რომელიც დიაგნოსტიკის ჯგუფს ეკუთვნის, მაგალითად, ფაილები /dev-ში. ამან შესაძლოა იმოქმედოს სისტემის სტაბილურობასა და უსაფრთხოებაზე. მისი გამოყენება მხოლოდ მწარმოებლის ან ოპერატორის მიერ ტექნიკის სპეციფიკური დიაგნოსტიკისთვის უნდა მოხდეს."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"აპის კომპონენტების ჩართვა ან გამორთვა"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 9c48eed..e8c8bb4 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"ឲ្យ​កម្មវិធី​អាន​ពី​ឯកសារ​កំណត់ហេតុ​ប្រព័ន្ធ។ វា​អនុញ្ញាត​ឲ្យ​រក​មើល​ព័ត៌មាន​ទូទៅ​អំពី​អ្វី​ដែល​អ្នក​កំពុង​ធ្វើជា​មួយ​កុំព្យូទ័រ​បន្ទះ សំខាន់​រួមមាន​ព័ត៌មាន​ផ្ទាល់​ខ្លួន​ ឬ​ឯកជន។"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"ប្រើ​កម្មវិធី​ឌិកូដ​​មេឌៀ​ណា​មួយ​សម្រាប់​ចាក់​ឡើងវិញ"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"ឲ្យ​កម្មវិធី​ប្រើ​កម្មវិធី​ឌិកូដ​មេឌៀ​ដែល​បាន​ដំឡើង ដើម្បី​ឌិកូដ​សម្រាប់​ការ​ចាក់​ឡើងវិញ។"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"អាន/សរសេរ​ធនធាន​គ្រប់គ្រង​ប្រអប់"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"ឲ្យ​កម្មវិធី​អាន និង​សរសេរ​ប្រភព​ណាមួយ​ដែល​គ្រប់គ្រង​ដោយ​ក្រុម​អ្នក​វិនិច្ឆ័យ ឧទាហរណ៍ ឯកសារ​នៅ​ក្នុង /dev ។ វា​អាច​ប៉ះពាល់​យ៉ាង​ខ្លាំង​ដល់​ស្ថេរ​ភាព​ និង​សុវត្ថិភាព​ប្រព័ន្ធ។ វា​គួរ​ត្រូវ​បាន​ប្រើ​សម្រាប់​វិនិច្ឆ័យ​ផ្នែក​រឹង​ជាក់​លាក់​ដោយ​ក្រុមហ៊ុន​ផលិត ឬ​ប្រតិបត្តិ​ករ។"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"បិទ ឬ​បើក​សមាសធាតុ​កម្មវិធី"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 3576d18..c05ec92 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"앱이 시스템의 다양한 로그 파일을 읽을 수 있도록 허용합니다. 이렇게 되면 앱이 개인정보 또는 비공개 정보를 포함하여 휴대전화로 수행하는 작업에 대한 일반적인 정보를 검색할 수 있습니다."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"재생에 모든 미디어 디코더 사용"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"애플리케이션에서 설치된 모든 미디어 디코더를 사용하여 재생하는 데 디코딩할 수 있도록 허용합니다."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"진단 그룹 소유의 리소스 읽기/쓰기"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"앱이 진단 그룹 소유의 리소스(예: /dev에 있는 파일)를 읽고 쓸 수 있도록 허용합니다. 이 기능은 시스템 안정성 및 보안에 영향을 미칠 수 있으므로 제조업체 또는 사업자가 하드웨어 관련 진단을 수행하는 경우에만 사용해야 합니다."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"앱 구성요소 사용 또는 사용 안함"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index d853a50..9d07ae6 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"ອະນຸຍາດໃຫ້ແອັບຯອ່ານໄຟລ໌ບັນທຶກລະບົບຕ່າງໆຂອງລະບົບ. ຄຸນສົມບັດນີ້ຈະອະນຸຍາດໃຫ້ແອັບຯ ສາມາດຄົ້ນພົບຂໍ້ມູນທົ່ວໄປ ກ່ຽວກັບສິ່ງທີ່ທ່ານກຳລັງເຮັດກັບໂທລະສັບ ເຊິ່ງອາດຮວມເຖິງຂໍ້ມູນສ່ວນໂຕນຳໄດ້."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"ໃຊ້ຕົວຖອດລະຫັດໃດກໍໄດ້ເພື່ອການຫຼິ້ນ"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"ອະນຸຍາດໃຫ້ແອັບຯໃຊ້ທຸກຕົວຖອດລະຫັດສື່ທີ່ຕິດຕັ້ງໄວ້ແລ້ວ ເພື່ອການຖອດລະຫັດການຫຼິ້ນໄຟລ໌ຕ່າງໆ."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ອ່ານ/ຂຽນ ໃສ່ຊັບພະຍາກອນທີ່ເປັນຂອງກຸ່ມວິໄຈ"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນອ່ານ ແລະຂຽນ ໃສ່ທຸກຊັບພະຍາກອນທີ່ເປັນຂອງກຸ່ມວິນິໄສ; ຕົວຢ່າງ: ໄຟລ໌ໃນ /dev. ສິ່ງນີ້ອາດສົ່ງຜົນກະທົບຕໍ່ຄວາມສະຖຽນ ແລະຄວາມປອດໄພຂອງລະບົບ. ສິ່ງນີ້ຄວນໃຊ້ສຳຫຼັບການວິເຄາະບັນຫາຈຳເພາະ ຂອງບາງຮາດແວໂດຍຜູ່ຜະລິດ ຫຼືຜູ່ປະຕິບັດການເທົ່ານັ້ນ."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"ເປີດ ຫຼືປິດນຳໃຊ້ອົງປະກອບຂອງແອັບຯ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index cfe8a1c..8ba1194 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Leidžiama programai skaityti iš įvairių sistemos žurnalų failų. Taip galima atrasti bendrą informaciją apie tai, ką darote telefonu, potencialiai įtraukiant asmeninę ar privačią informaciją."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"atkuriant naudoti bet kurį medijos dekoderį"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Leidžiama programai naudoti bet kurį įdiegtą medijos dekoderį norint iššifruoti atkūrimą."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"skaityti / rašyti ištekliuose, priklausančiuose diagnostikai"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Leidžiama programai skaityti ir rašyti visuose diagnostikos grupei priklausančiuose ištekliuose, pvz., failuose, esančiuose /dev. Tai gali paveikti sistemos stabilumą ir saugą. Tai turėtų būti naudojama TIK gamintojui ar operatoriui atliekant aparatinės įrangos diagnostiką."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"įgalinti programos komponentus arba jų neleisti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 3fdcde2..1ab7053 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Ļauj lietotnei lasīt informāciju no dažādiem sistēmas žurnālfailiem. Šādi lietotne var atrast vispārīgu informāciju par jūsu darbībām tālrunī, tostarp arī personas vai privātu informāciju."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"multivides failu atskaņošanai izmantot jebkuru dekodētāju"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Ļauj lietotnei izmantot jebkuru instalētu multivides failu dekodētāju, lai dekodētu failus atskaņošanai."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lasīt grupas “diag” resursus un rakstīt tajos"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Ļauj lietotnei lasīt un rakstīt jebkurā resursā, kas pieder diagnostikas grupai, piemēram, failiem mapē /dev. Tas var ietekmēt sistēmas stabilitāti un drošību. Var izmantot ražotājs vai operators TIKAI konkrētas aparatūras diagnostikai."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"iespējot vai atspējot lietotnes komponentus"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8ed4dca..e0c9478 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Апп нь системийн төрөл бүрийн лог файлыг унших боломжтой. Энэ нь та утсан дээрээ юу хийсэн талаарх хувийн болон нууц мэдээллийг олох боломжтой болгоно."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"тоглуулахын тулд дурын медиа шифрлэгчийг ашиглах"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Апп нь тоглуулах үедээ код тайлахдаа суулгагдсан ямарч медиа код тайлагчийг ашиглах боломжтой."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"итгэмжлэгдсэн жуухуудыг удирдах"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Апп-д CA сертификатуудыг итгэмжлэгдсэн жуух байдлаар суулгах болон устгахыг зөвшөөрнө."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"оношлох грүпийн эзэмшдэг нөөцрүү унших/бичих"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Апп нь оношлох грүпийн эзэмшдэг, жишээ нь /dev доторх файлууд, дурын  нөөцийг унших бичих боломжтой.Энэ нь системийн тогвортой байдал болон аюулгүй байдалд бодитоор нөлөөлнө. Энэ нь үйлдвэрлэгч болон операторын хардверт-зориулсан оношлогоонд ашиглагдана."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"апп компонентыг идэвхжүүлэх эсвэл идэвхгүй болгох"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 6fac0d9..e6dc0ca 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Membenarkan apl membaca daripada pelbagai fail log sistem. Hal ini membenarkannya menemui maklumat umum mengenai perkara yang anda lakukan dengan telefon, juga berpotensi menyertakan maklumat persendirian dan peribadi."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"gunakan mana-mana penyahkod media untuk main semula"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Membenarkan apl untuk menggunakan sebarang penyahkod media yang dipasangkan untuk menyahkod main semula."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber yang dimiliki oleh diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Membenarkan apl membaca dan menulis ke sebarang sumber yang dimiliki oleh kumpulan diag; contohnya, fail dalam /dev. Hal ini berpotensi menjejaskan kestabilan dan keselamatan sistem. Perkara ini seharusnya HANYA digunakan untuk diagnosis khusus perkakasan oleh pengilang atau pengendali."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"dayakan atau lumpuhkan komponen apl"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9b9d58e..46ffaa3 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Lar appen lese fra diverse loggfiler på systemet. Disse inneholder generell informasjon om hva som gjøres med telefonen, og kan inneholde personlig eller privat informasjon."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"bruke en hvilken som helst mediedekoder for avspilling"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Lar appen bruke en hvilken som helst installert mediedekoder for å dekode for avspilling."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"administrer pålitelig legitimasjon"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Lar appen installere og avinstallere CA-sertifikater som pålitelig legitimasjon."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lese/skrive ressurser eid av diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Lar appen lese og skrive til alle ressurser som eies av gruppen «diag», som for eksempel filer i /dev. Dette kan potensielt påvirke systemets sikkerhet og stabilitet. Dette bør BARE brukes av produsenten eller operatøren til maskinvarespesifikk diagnostikk."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktivere eller deaktivere appkomponenter"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 7504236..b6e4fc3 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"प्रणालीका विभिन्न फाइलहरूबाट पढ्न अनुप्रयोगलाई अनुमति दिन्छ। सम्भाव्य रूपमा व्यक्तिगत र निजी सूचनासहित तपाईँ फोनसँग के गरिरहनु भएको छ भन्ने बारेको साधारण सूचना पत्ता लगाउन यसलाई अनुमति दिन्छ।"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"पछाडि बजाउनको लागि कुनै मिडिया प्रयोग गर्नुहोस्"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"अनुप्रयोगलाई प्लेब्याक डिकोड गर्न कुनै पनि स्थापित मिडिया डिकोडर प्रयोगको लागि अनुमति दिन्छ।"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"diag को स्वामित्वमा रहेको संसाधनहरूमा पढ्नुहोस्/लेख्नुहोस्"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"अनुप्रयोगलाई diag समूहद्वारा स्वामित्व प्राप्त कुनै पनि स्रोतहरूमा पढ्न र लेख्न अनुमति दिन्छ; उदाहरणको लागि, /dev  मा फाइलहरू। यसले सम्भवतः प्रणाली स्थिरता र सुरक्षामा प्रभाव पार्न सक्दछ। यो केवल निर्माता वा संचालकद्वारा हार्डवेयर-निर्दिष्टको लागि प्रयोग हुन सक्दछ।"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"अनुप्रयोग अंशहरू सक्षम वा अक्षम गर्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index c219fde..94bdd68 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Hiermee kan de app de verschillende logbestanden van het systeem lezen. De app kan op deze manier algemene informatie achterhalen over uw telefoongebruik, mogelijk inclusief persoonlijke of privé-informatie."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"elke mediadecoder gebruiken voor afspelen"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Hiermee kan de app alle geïnstalleerde mediadecoders gebruiken om te decoderen voor het afspelen."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"vertrouwde inloggegevens beheren"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Hiermee kan de app CA-certificaten installeren en verwijderen als vertrouwde inloggegevens."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lezen/schrijven naar bronnen van diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Hiermee kan de app lezen en schrijven naar elke bron die hoort bij de diagnostische groep, zoals bestanden in /dev. Hierdoor kan de systeemstabiliteit en -veiligheid worden beïnvloed. Dit mag ALLEEN worden gebruikt voor hardwarespecifieke diagnostiek door de fabrikant of provider."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"componenten van apps in- of uitschakelen"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7f67e82..6f7db9d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Pozwala aplikacji na odczyt różnych plików dzienników systemowych. Dzięki temu może ona poznać ogólne informacje na temat korzystania z telefonu, co potencjalnie może obejmować również informacje prywatne lub osobiste."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"użycie dowolnego dekodera multimediów w celu odtwarzania"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Pozwala aplikacji na użycie dowolnego zainstalowanego dekodera multimediów do odtwarzania."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"czytanie/zapisywanie w zasobach należących do diagnostyki"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Pozwala aplikacji na czytanie i zapisywanie wszystkich zasobów należących do grupy diagnostyki, na przykład plików w katalogu /dev. Może to potencjalnie wpłynąć na stabilność i bezpieczeństwo systemu. Powinno być wykorzystywane WYŁĄCZNIE do diagnozowania sprzętu przez producenta lub operatora."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"włączanie lub wyłączanie składników aplikacji"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 70bfdc3..6e8dd95 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permite que a aplicação leia a partir dos diversos ficheiros de registo do sistema. Isto permite descobrir informações gerais sobre a forma como o utilizador usa o telemóvel, podendo, inclusive, incluir dados pessoais ou privados."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Utilizar qualquer descodificador de multimédia para a reprodução"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permite que a aplicação utilize qualquer descodificador de multimédia instalado para descodificar a reprodução."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"gerir credenciais fidedignas"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Permite que a aplicação instale e desinstale certificados da AC (Autoridade de certificação) como credenciais fidedignas."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ler/escrever em recursos propriedade de diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permite à aplicação ler e escrever em qualquer recurso que seja propriedade do grupo diag; por exemplo, ficheiros em /dev. Isto pode potencialmente afetar a estabilidade e a segurança do sistema e deve ser utilizado APENAS para diagnósticos específicos do hardware pelo fabricante ou pelo operador."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"ativar ou desativar componentes da aplicação"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 1973d86..7a8d8a7 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permite que o aplicativo leia os diversos arquivos de registro do sistema. Isso permite que ele descubra informações gerais sobre o que você está fazendo com o telefone, inclusive possíveis informações pessoais ou privadas."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"usar qualquer decodificador de mídia para reprodução"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permite que o aplicativo use qualquer decodificador de mídia instalado para reprodução."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"gerenciar credenciais confiáveis"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Permite que o aplicativo instale e desinstale certificados CA como credenciais confiáveis."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"ler/gravar em recursos pertencentes ao diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permite que um aplicativo leia e grave em qualquer recurso que pertença ao grupo de diagnósticos, por exemplo, arquivos in/dev. Isso pode afetar a estabilidade e a segurança do sistema. Esse recurso deve ser usado APENAS para diagnósticos específicos do hardware realizados pelo fabricante ou pela operadora."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"ativar ou desativar os componentes do aplicativo"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 7afb03e..93d3fad 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -652,6 +652,10 @@
     <skip />
     <!-- no translation found for permdesc_anyCodecForPlayback (8283912488433189010) -->
     <skip />
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"leger/scriver en resursas che appartegnan a diagnostics"</string>
     <!-- no translation found for permdesc_diagnostic (6608295692002452283) -->
     <skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 31cb5b3..edbf9dc 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Permite aplicaţiei să citească din diverse fişiere jurnal ale sistemului. În acest mod poate descoperi informaţii generale cu privire la utilizarea telefonului de către dvs., care ar putea include şi informaţii personale sau private."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"utilizaţi orice decodor media pentru redare"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permite aplicaţiei să utilizeze orice decodor media instalat pentru a decodifica redarea."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"citire/scriere în resursele deţinute de diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permite aplicaţiei să citească şi să scrie în orice resursă deţinută de grupul diag, de ex., fişierele din /dev. Această permisiune ar putea să afecteze stabilitatea şi securitatea sistemului. Permisiunea trebuie utilizată NUMAI de producător sau de operator pentru diagnostice specifice pentru hardware."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"activare sau dezactivare a componentelor aplicaţiei"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 07ffda4..72b9977 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Приложение сможет считывать информацию из различных системных журналов, а также получать сведения о работе пользователя на телефоне, в том числе к личной и конфиденциальной информации."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Использование любых дешифраторов"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Приложение сможет использовать любой установленный дешифратор."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Чтение/запись данных в системы диагностики"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Приложение сможет считывать и записывать данные системы диагностики (например, файлы в каталоге /dev). Это может повлиять на стабильность и безопасность системы. Это разрешение должно использоваться ТОЛЬКО производителем или оператором для диагностики аппаратного обеспечения."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"Включение/отключение компонентов приложения"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index f36a83f..165163b 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"පද්ධතියේ විවිධ ලොග් ගොනු කියවීමට යෙදුමට අවසර දෙන්න. පුද්ගලික සහ පෞද්ගලික තොරතුරු ඇතුළත්ව ඔබ දුරකථනයෙන් කුමක් කරන්නෙහිද යනාදී සාමාන්‍ය තොරතුරු සෙවීමට මෙයට අවසර දෙන්න."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"නැවත ධාවනය සඳහා ඕනෑම මාධ්‍ය විකේතකයක් හාවිතා කරන්න"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"නැවත ධාවනය සඳහා විකේතනය කිරීමට ඕනෑම ස්ථාපිත මාධ්‍ය විකේතකයක් භාවිතයට යෙදුමට අවසර දෙන්න."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Diag විසින් හිමිකාරත්වය දරණ සම්පත්වලට කියවීම/ ලිවිම"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Diag කණ්ඩායමට අයිති ඕනෑම සම්පතක් කියවීමට සහ ලිවීමට යෙදුමට අවසර දෙන්න. උදාහරණයක් ලෙස /dev තුල ඇති ගොනු. මෙයට පද්ධති ස්ථායිතාවට සහ ආරක්ෂාවට බලපෑම් කිරීමට හැකියාවක් ඇත. නිෂ්පාදක හෝ ක්‍රියාකරු විසින් දෘඩාංග-විශේෂිත දෝෂ නිර්ණය සඳහා පමණක් මෙය යොදාගත යුතුය."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"යෙදුම් අංග සබල හෝ අබල කිරීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 5c4e558..5554db3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Umožňuje aplikácii čítať rôzne systémové súbory denníkov. Toto nastavenie aplikácii umožňuje získať všeobecné informácie o činnostiach s telefónom, ktoré by mohli obsahovať osobné alebo súkromné informácie."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"použiť ľubovoľný dekódovač médií na reprodukciu"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Umožňuje aplikácii používať na reprodukciu ľubovoľný nainštalovaný dekódovač na dekódovanie."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"čítanie alebo zápis do prostriedkov funkcie diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Umožňuje aplikácii čítať ľubovoľné prostriedky v skupine diag, napr. súbory v priečinku /dev, a zapisovať do nich. Môže dôjsť k ovplyvneniu stability a bezpečnosti systému. Toto nastavenie by mal používať IBA výrobca či operátor na diagnostiku hardvéru."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"povoliť alebo zakázať súčasti aplikácie"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 2a68043..0a53f49 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Programu omogoča branje različnih sistemskih dnevniških datotek. To mu omogoča dostop do splošnih podatkov v telefonu, lahko tudi do osebnih podatkov."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"uporaba katerega koli predstavnostnega dekodirnika za predvajanje"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Programu omogoča, da uporabi kateri koli dekodirnik večpredstavnosti za predvajanje."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"upravljanje preverjenih poverilnic"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Aplikaciji dovoli nameščanje in odstranjevanje potrdil overitelja potrdil kot preverjenih poverilnic."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"branje/pisanje v sredstva, ki so v lasti skupine za diagnostiko"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Programu omogoča branje in pisanje na poljuben vir, ki je v lasti skupine za diagnostiko; na primer datoteke v mapi /dev. To lahko vpliva na stabilnost in varnost sistema. To naj uporablja SAMO izdelovalec ali operater za diagnostiko, specifično za strojno opremo."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"omogočanje ali onemogočanje komponent programa"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index aa8eef3..9081482 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Дозвољава апликацији да чита разне системске датотеке евиденције. То јој омогућава увид у опште информације о начину на који користите телефон, при чему могу да буду обухваћене личне или приватне информације."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"користи било који декодер медија за репродукцију"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Омогућава апликацији да користи било који инсталирани декодер медија за декодирање за репродукцију."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"читање ресурса у власништву дијагностике и уписивање података у њих"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Дозвољава апликацији да чита и уписује податке у било који ресурс у власништву групе за дијагностиковање, на пример, датотеке у директоријуму /dev. То може да угрози стабилност и безбедност система и треба да је користе САМО произвођач или оператер у сврхе дијагностиковањa хардвера."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"омогућавање или онемогућавање компоненти апликације"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 37b98c2..62d7330 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Tillåter att appen läser från systemets olika loggfiler. Det innebär att appen kan upptäcka allmän information om vad du gör med mobilen, vilket kan inkludera personlig eller privat information."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"använda alla medieavkodare för uppspelning"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Tillåter att appen använder installerade medieavkodare för att avkoda media för uppspelning."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"läsa/skriva till resurser som ägs av diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Tillåter att appen läser och skriver till en resurs som ägs av diag-gruppen, till exempel filer i /dev. Detta kan eventuellt påverka systemets stabilitet och säkerhet. Detta bör ENDAST användas av tillverkaren eller operatören för maskinvaruspecifik diagnostik."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktivera eller inaktivera appkomponenter"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index fb98656..57a4c95 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Inaruhusu programu kusoma kutoka kwa faili mbalimbali za kumbukumbu za mfumo. Hii inairuhusu kutambua maelezo ya jumla kuhusu unachofanya na simu, yanayoweza kujumuisha maelezo ya kibinafsi na ya siri."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"Tumia chombo chochote cha habari cha kufasiria maandishi ya siri ili kucheza tena."</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Huruhusu programu kutumia vyombo vyovyote vya habari vilivyosakinishwa ili kusimbua kwa ajili ya kucheza tena."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"soma/andika kwa vyanzo vinavyomilikiwa na diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Inaruhusu programu kusoma na kuandika kwa chanzo chochote kinachomilikiwa na kikundi cha diag; kwa mfano, faili katika /dev. Hii inaweza kuathiri udhabiti na usalama wa mfumo. Hii inapaswa kutumiwa TU kwa utambuzi mahsusi wa maunzi na mtengenezaji au opareta."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"wezesha au lemeza vijenzi vya programu"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index baf9b2e..c5cc4f5 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"อนุญาตให้แอปพลิเคชันอ่านจากไฟล์บันทึกต่างๆ ของระบบ เพื่อค้นหาข้อมูลทั่วไปเกี่ยวกับสิ่งที่คุณกำลังทำอยู่กับโทรศัพท์ ซึ่งอาจรวมไปถึงข้อมูลส่วนบุคคลหรือส่วนตัว"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"ใช้ตัวถอดรหัสสื่อใดๆ ก็ได้สำหรับการเล่น"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"อนุญาตให้แอปพลิเคชันใช้ตัวถอดรหัสสื่อใดก็ได้ที่ติดตั้งไว้เพื่อถอดรหัสสำหรับการเล่น"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"อ่าน/เขียนไปยังรีซอร์สที่เป็นเจ้าของโดยกลุ่มวินิจฉัย"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"อนุญาตให้แอปพลิเคชันอ่านและเขียนไปยังทรัพยากรที่เป็นของกลุ่มวินิจฉัย เช่น ไฟล์ใน /dev การทำเช่นนี้อาจส่งผลต่อความเสถียรและความปลอดภัยของระบบ และควรใช้สำหรับการวินิจฉัยเกี่ยวกับฮาร์ดแวร์โดยเฉพาะที่ทำโดยผู้ผลิตหรือผู้ให้บริการเท่านั้น"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"เปิดหรือปิดใช้งานคอมโพเนนต์ของแอปพลิเคชัน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 42c4268..87fc3d6 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Pinapayagan ang app na magbasa mula sa iba\'t ibang mga file ng log ng system. Pinapayagan ito nito na tumuklas ng pangkalahatang impormasyon tungkol sa kung ano ang iyong ginagawa sa telepono, potensyal na kabilang ang personal o pribadong impormasyon."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"gumamit ng anumang media decoder para sa pag-playback"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Pinapayagan ang app na gumamit ng anumang naka-install na media decoder upang mag-decode para sa pag-playback."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"magbasa/magsulat sa mga mapagkukunang pag-aari ng diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Pinapayagan ang app na magbasa at magsulat sa anumang mapagkukunang pag-aari ng pangkat ng diag; halimbawa, mga file sa /dev. Maaaring potensyal na maapektuhan nito ang katatagan at seguridad ng system. Dapat LAMANG itong gamitin para sa diagnostics na tukoy sa hardware ng tagagawa o operator."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"paganahin o huwag paganahin ang mga bahagi ng app"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 960c3cc..310e6fe 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Uygulamaya, sisteme ait çeşitli günlük dosyalarındaki bilgileri okuma izni verir. Bu izin, uygulamanın, kişisel ve gizli bilgileriniz de dahil olmak üzere telefonda yaptıklarınızla ilgili genel bilgileri bulmasına olanak verir."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"oynatma için herhangi bir medya kod çözücüyü kullan"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Uygulamaya, oynatma kodunu çözmek için herhangi bir yüklü medya kod çözücüyü kullanma izni verir."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"sahibi tanılama olan kaynakları oku/bunlara yaz"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Uygulamaya, tanılama grubunun sahip olduğu tüm kaynaklara (örneğin /dev içindeki dosyalar) okuma ve yazma izni verir. Bu işlevin sistem kararlılığını ve güvenliğini olumsuz etkileme olasılığı vardır. Üretici veya operatör tarafından YALNIZCA donanıma özgü tanılama için kullanılmalıdır."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"uygulama bileşenlerini etkinleştir veya devre dışı bırak"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index de4267f..bd9c508 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -407,6 +407,8 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Дозволяє програмі читати з різних файлів журналу системи. Це дозволяє дізнаватися загальну інформацію про ваші дії в телефоні, яка потенційно може містити особисті чи конфіденційні дані."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"використовувати будь-який медіа-декодер для відтворення"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Дозволяє програмі використовувати будь-який установлений медіа-декодер для декодування з метою відтворення."</string>
+    <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"керувати захищеними обліковими даними"</string>
+    <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Дозволяє програмі встановлювати та видаляти сертифікати центру сертифікації (CA) як захищені облікові дані."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"чит./зап. на ресури., якими вол. діаг."</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Дозволяє програмі читати та писати на будь-який ресурс, яким володіє діагностична група; наприклад, у файли в папці /dev. Це потенційно може вплинути на стабільність і безпеку системи. Потрібно використовувати ЛИШЕ для певної діагностики обладнання, яку виконує виробник чи оператор."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"вмикати чи вимикати компоненти програми"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 400ab70..54d422d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Cho phép ứng dụng đọc từ nhiều tệp nhật ký khác nhau của hệ thống. Quyền này cho phép ứng dụng phát hiện thông tin chung về những gì bạn đang thực hiện với điện thoại, có thể bao gồm thông tin cá nhân hoặc riêng tư."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"sử dụng bất kỳ bộ giải mã phương tiện nào để phát lại"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Cho phép ứng dụng sử dụng bất kỳ trình giải mã phương tiện nào đã cài đặt nhằm giải mã để phát lại."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"đọc/ghi vào tài nguyên do chẩn đoán sở hữu"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Cho phép ứng dụng đọc và ghi vào bất kỳ tài nguyên nào do nhóm chẩn đoán sở hữu; ví dụ: các tệp trong /dev. Quyền này có thể ảnh hưởng đến sự ổn định và tính bảo mật của hệ thống. CHỈ nên sử dụng quyền này cho các chẩn đoán phần cứng cụ thể của nhà sản xuất hoặc nhà cung cấp."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"bật hoặc tắt cấu phần ứng dụng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 847316a..22e526a4 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"允许应用从系统的各个日志文件中读取信息。这样,应用就可以发现关于您手机使用情况的一般信息,其中可能包含个人信息或隐私信息。"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"使用任何媒体解码器进行播放"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"允许该应用使用任何已安装的媒体解码器进行解码,以便播放媒体。"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"读取/写入诊断所拥有的资源"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"允许应用读取/写入诊断组拥有的所有资源(例如 /dev 中的文件)。这可能会影响系统的稳定性和安全性。此权限仅供制造商或运营商诊断硬件方面的问题时使用。"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"启用或停用应用组件"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a7dd3ce..0c73dde 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"允許應用程式讀取系統的各種記錄檔。這會允許應用程式查看一般的電話使用資訊,可能包括您的個人或私人資訊。"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"使用任何媒體解碼器進行播放"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"允許應用程式使用任何已安裝的媒體解碼器為播放解碼。"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"讀取/寫入由診斷應用程式擁有的資源"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"允許應用程式讀取及寫入診斷群組所擁有的任何資源 (例如:位於 /dev 中的檔案)。這可能會影響系統的穩定性及安全性,只應對製造商或網絡供應商所使用的硬件專用診斷程式開放這項權限。"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"啟用或停用應用程式元件"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index d9413f8..94086e6 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"允許應用程式讀取系統的各種記錄檔。這會允許應用程式搜尋一般性的手機使用資訊,可能包含您的個人或私人資訊。"</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"使用任何媒體解碼器進行播放"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"允許應用程式使用任何已安裝的媒體解碼器進行解碼以播放影片。"</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"讀寫 diag 擁有的資源"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"允許應用程式讀取或寫入診斷群組擁有的任何資源,例如 /dev 底下的檔案。這可能會影響系統的穩定性和安全性,因此應由製造商或電信業者操作,且只用在特定硬體診斷。"</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"啟用或停用應用程式元件"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 0b03f89..2f8a0be 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -407,6 +407,10 @@
     <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Ivumela uhlelo lokusebenza ukufunda kumafayela okungena ahlukene esistimu. Lokhu kuvumela ukuthola ukwaziswa okuvamile mayelana nokuthi wenzani ngefoni, kuhlanganise ukwaziswa komuntu siqu noma kwangasese."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"sebenzisa noma isiphi isiqophi semidiya ukudlala"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Ivumela insiza ukusebenzisa noma isiphi isiqophi semidiya esifakiwe ukuqopha ukudlala."</string>
+    <!-- no translation found for permlab_manageCaCertificates (1678391896786882014) -->
+    <skip />
+    <!-- no translation found for permdesc_manageCaCertificates (4015644047196937014) -->
+    <skip />
     <string name="permlab_diagnostic" msgid="8076743953908000342">"funda/bhalela emithombweni ephethwe idayegi"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Ivumela uhlelo lokusebenza ukufunda nokubhala kunoma yimuphi umthombo weqembu ledayegi; ngokwesibonelo, amafayela akwi/dev. Lokhu kungase kuthinte kakhulu ukuba nokuphepha kohlelo. Lokhu kumele kusebenziselwe KUPHELA ukuhlola ihadiwe okucacile ngumkhiqizi noma u-opheretha."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"vumela noma vimbela izingxenye zensiza"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 400e892..4116998 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -123,12 +123,8 @@
          of them.  This should not normally be modified. -->
     <bool name="config_closeDialogWhenTouchOutside">true</bool>
 
-    <!-- Device configuration indicating this is a device with limited RAM, so heavier-weight
-         features should be turned off. -->
-    <bool name="config_lowRamDevice">false</bool>
-
     <!-- Device configuration indicating whether we should avoid using accelerated graphics
-         in certain places to reduce RAM footprint.  This is ignored if config_lowRamDevice
+         in certain places to reduce RAM footprint.  This is ignored if ro.config.low_ram
          is true (in that case this is assumed true as well).  It can allow you to tune down
          your device's memory use without going to the point of causing applications to turn
          off features. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 00caac9..e902354 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -344,4 +344,16 @@
     security mode. -->
     <dimen name="kg_small_widget_height">160dp</dimen>
 
+    <!-- Rounded corner radius for video subtitles. -->
+    <dimen name="subtitle_corner_radius">2dp</dimen>
+
+    <!-- Shadow radius for video subtitles. -->
+    <dimen name="subtitle_shadow_radius">2dp</dimen>
+
+    <!-- Shadow offset for video subtitles. -->
+    <dimen name="subtitle_shadow_offset">2dp</dimen>
+
+    <!-- Outline width for video subtitles. -->
+    <dimen name="subtitle_outline_width">2dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e497c85..5f5564c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1128,6 +1128,11 @@
     <string name="permdesc_anyCodecForPlayback">Allows the app to use any installed
         media decoder to decode for playback.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. This permission allows the app to install or uninstall trusted credentials, a.k.a. CA certificates. [CHAR LIMIT=NONE] -->
+    <string name="permlab_manageCaCertificates">manage trusted credentials</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE]-->
+    <string name="permdesc_manageCaCertificates">Allows the app to install and uninstall CA certificates as trusted credentials.</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_diagnostic">read/write to resources owned by diag</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ca93d1c..8d3e474 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -252,7 +252,6 @@
   <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
   <java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
   <java-symbol type="bool" name="config_enable_puk_unlock_screen" />
-  <java-symbol type="bool" name="config_lowRamDevice" />
   <java-symbol type="bool" name="config_mms_content_disposition_support" />
   <java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
   <java-symbol type="bool" name="config_sip_wifi_only" />
@@ -1662,4 +1661,9 @@
   <java-symbol type="attr" name="actionModeWebSearchDrawable" />
   <java-symbol type="string" name="websearch" />
 
+  <!-- From SubtitleView -->
+  <java-symbol type="dimen" name="subtitle_corner_radius" />
+  <java-symbol type="dimen" name="subtitle_shadow_radius" />
+  <java-symbol type="dimen" name="subtitle_shadow_offset" />
+  <java-symbol type="dimen" name="subtitle_outline_width" />
 </resources>
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index 9fdfd0e..a570802 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -306,5 +306,61 @@
         for (LinkProperties link : rmnet0.getStackedLinks()) {
             assertFalse("newname".equals(link.getInterfaceName()));
         }
+
+        assertTrue(rmnet0.removeStackedLink(clat4));
+        assertEquals(0, rmnet0.getStackedLinks().size());
+        assertEquals(1, rmnet0.getAddresses().size());
+        assertEquals(1, rmnet0.getLinkAddresses().size());
+        assertEquals(1, rmnet0.getAllAddresses().size());
+        assertEquals(1, rmnet0.getAllLinkAddresses().size());
+
+        assertFalse(rmnet0.removeStackedLink(clat4));
+    }
+
+    @SmallTest
+    public void testAddressMethods() {
+        LinkProperties lp = new LinkProperties();
+
+        // No addresses.
+        assertFalse(lp.hasIPv4Address());
+        assertFalse(lp.hasIPv6Address());
+
+        // Addresses on stacked links don't count.
+        LinkProperties stacked = new LinkProperties();
+        stacked.setInterfaceName("stacked");
+        lp.addStackedLink(stacked);
+        stacked.addLinkAddress(LINKADDRV4);
+        stacked.addLinkAddress(LINKADDRV6);
+        assertTrue(stacked.hasIPv4Address());
+        assertTrue(stacked.hasIPv6Address());
+        assertFalse(lp.hasIPv4Address());
+        assertFalse(lp.hasIPv6Address());
+        lp.removeStackedLink(stacked);
+        assertFalse(lp.hasIPv4Address());
+        assertFalse(lp.hasIPv6Address());
+
+        // Addresses on the base link.
+        // Check the return values of hasIPvXAddress and ensure the add/remove methods return true
+        // iff something changes.
+        assertTrue(lp.addLinkAddress(LINKADDRV6));
+        assertFalse(lp.hasIPv4Address());
+        assertTrue(lp.hasIPv6Address());
+
+        assertTrue(lp.removeLinkAddress(LINKADDRV6));
+        assertTrue(lp.addLinkAddress(LINKADDRV4));
+        assertTrue(lp.hasIPv4Address());
+        assertFalse(lp.hasIPv6Address());
+
+        assertTrue(lp.addLinkAddress(LINKADDRV6));
+        assertTrue(lp.hasIPv4Address());
+        assertTrue(lp.hasIPv6Address());
+
+        // Adding an address twice has no effect.
+        // Removing an address that's not present has no effect.
+        assertFalse(lp.addLinkAddress(LINKADDRV4));
+        assertTrue(lp.hasIPv4Address());
+        assertTrue(lp.removeLinkAddress(LINKADDRV4));
+        assertFalse(lp.hasIPv4Address());
+        assertFalse(lp.removeLinkAddress(LINKADDRV4));
     }
 }
diff --git a/docs/html/samples/samples_toc.cs b/docs/html/samples/samples_toc.cs
index 8fcd676..14a5b0a9d 100644
--- a/docs/html/samples/samples_toc.cs
+++ b/docs/html/samples/samples_toc.cs
@@ -1,5 +1,5 @@
 
-<ul id="nav">
+<ul id="nav" class="samples-nav">
 
 <script type="text/javascript">
 <!--
@@ -8,16 +8,9 @@
 //-->
 </script>
   <li class="nav-section">
-    <div class="nav-section-header"><a href="/samples/index.html">
+    <div class="nav-section-header empty"><a href="/samples/index.html">
       <span class="en">About the Samples</span></a>
     </div>
-   
   </li>
-
-  <li id="samples-tree-list" class="nav-section">
-    <div class="nav-section-header"><a href="/samples/index.html">
-      <span class="en">Root Node (remove)</span></a>
-    </div>
-  </li>
-  </ul>
+</ul>
 
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index 820edbd..7cf3735 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -22,20 +22,31 @@
 
 
 
-<p>To develop an Android app, you must install at least one Android platform from the SDK Manager
-against which you can compile your app. Often, any given version of the Android will be revised
-with bug fixes or other changes, as denoted by the revision number. Below, you'll find the
-release notes for each version of the platform and the subsequent revisions to the platform
-version.</p>
+<p>This document provides information about Android platform releases. In order to compile your
+application against a particular platform release, you must download and install the SDK Platform
+for that release. If you want to test your application on an emulator, you must also download at
+least one system image for that platform release.</p>
 
-<p>To determine what revision of an Android platform you have installed, refer to the
-<strong>Installed Packages</strong> listing in the Android
+<p>Each platform release includes system images that support a specific processor architecture,
+such as ARM EABI, Intel x86 or MIPS. Platform releases also include a system image that contains
+Google APIs. The <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> lists available
+platform system images under each platform version header, for example:</p>
+
+<ul>
+  <li>ARM EABI v7a System Image</li>
+  <li>Intel x86 Atom System Image</li>
+  <li>MIPS System Image</li>
+  <li>Google APIs</li>
+</ul>
+
+<p>To determine what revisions of an Android platform you have installed, refer to the
+<em>Packages</em> listing in the Android
 <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a>.</p>
 
 <p class="caution"><strong>Important:</strong> To download the most recent Android
-system components from the Android SDK Manager, you must first update the SDK Tools to
-revision 22 or later and restart the SDK Manager. If you do not,
-the latest Android system components will not be available for download.</p>
+system components from the Android SDK Manager, you must first update the SDK Tools to the
+most recent release and restart the SDK Manager. If you do not, the latest Android system
+components will not be available for download.</p>
 
 
 
@@ -46,6 +57,25 @@
 
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 2</a> <em>(August 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Maintenance update. The system version is 4.3.</p>
+    <dl>
+      <dt>Dependencies:</dt>
+      <dd>Android SDK Platform-tools r18 or higher is required.</dd>
+      <dd>Android SDK Tools 22.0.4 or higher is recommended.</dd>
+    </dl>
+
+  </div>
+</div>
+
+<div class="toggle-content closed">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png"
 class="toggle-content-img" alt="" />Revision 1</a> <em>(July 2013)</em>
   </p>
 
@@ -61,6 +91,39 @@
   </div>
 </div>
 
+<h3 id="">Google APIs System Image</h3>
+
+<div class="toggle-content opened">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 2</a> <em>(August 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Maintenance update. This release includes
+    <a href="{@docRoot}google/play-services/index.html">Google Play Services</a> version 3.2.25,
+    allowing you to test your application in an emulator using the latest Google Play Services.</p>
+
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />Revision 1</a> <em>(July 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Initial release. This release includes
+    <a href="{@docRoot}google/play-services/index.html">Google Play Services</a> version 3.1.58.</p>
+
+  </div>
+</div>
+
+
+
 
 <h2 id="4.2">Android 4.2</h2>
 
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 47cf875..c971da5 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -57,10 +57,20 @@
     private final BitmapFinalizer mFinalizer;
 
     private final boolean mIsMutable;
+
+    /**
+     * Represents whether the Bitmap's content is expected to be pre-multiplied.
+     * Note that isPremultiplied() does not directly return this value, because
+     * isPremultiplied() may never return true for a 565 Bitmap.
+     *
+     * setPremultiplied() does directly set the value so that setConfig() and
+     * setPremultiplied() aren't order dependent, despite being setters.
+     */
+    private boolean mIsPremultiplied;
     private byte[] mNinePatchChunk;   // may be null
     private int[] mLayoutBounds;   // may be null
-    private int mWidth = -1;
-    private int mHeight = -1;
+    private int mWidth;
+    private int mHeight;
     private boolean mRecycled;
 
     // Package-scoped for fast access.
@@ -89,32 +99,26 @@
     }
 
     /**
-     * Private constructor that must received an already allocated native
-     * bitmap int (pointer).
-     */
-    @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
-    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
-            int density) {
-        this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
-    }
-
-    /**
      * Private constructor that must received an already allocated native bitmap
      * int (pointer).
      */
     @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
-    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
-            int[] layoutBounds, int density) {
+    Bitmap(int nativeBitmap, byte[] buffer, int width, int height, int density,
+            boolean isMutable, boolean isPremultiplied,
+            byte[] ninePatchChunk, int[] layoutBounds) {
         if (nativeBitmap == 0) {
             throw new RuntimeException("internal error: native bitmap is 0");
         }
 
+        mWidth = width;
+        mHeight = height;
+        mIsMutable = isMutable;
+        mIsPremultiplied = isPremultiplied;
         mBuffer = buffer;
         // we delete this in our finalizer
         mNativeBitmap = nativeBitmap;
         mFinalizer = new BitmapFinalizer(nativeBitmap);
 
-        mIsMutable = isMutable;
         mNinePatchChunk = ninePatchChunk;
         mLayoutBounds = layoutBounds;
         if (density >= 0) {
@@ -123,11 +127,14 @@
     }
 
     /**
-     * Native bitmap has been reconfigured, so discard cached width/height
+     * Native bitmap has been reconfigured, so set premult and cached
+     * width/height values
      */
     @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
-    void reinit() {
-        mWidth = mHeight = -1;
+    void reinit(int width, int height, boolean isPremultiplied) {
+        mWidth = width;
+        mHeight = height;
+        mIsPremultiplied = isPremultiplied;
     }
 
     /**
@@ -206,7 +213,7 @@
             throw new IllegalStateException("only mutable bitmaps may be reconfigured");
         }
         if (mBuffer == null) {
-            throw new IllegalStateException("only non-purgeable bitmaps may be reconfigured");
+            throw new IllegalStateException("native-backed bitmaps may not be reconfigured");
         }
 
         nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length);
@@ -543,6 +550,7 @@
         checkRecycled("Can't copy a recycled bitmap");
         Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
         if (b != null) {
+            b.mIsPremultiplied = mIsPremultiplied;
             b.mDensity = mDensity;
         }
         return b;
@@ -719,6 +727,7 @@
         // The new bitmap was created from a known bitmap source so assume that
         // they use the same density
         bitmap.mDensity = source.mDensity;
+        bitmap.mIsPremultiplied = source.mIsPremultiplied;
         
         canvas.setBitmap(bitmap);
         canvas.drawBitmap(source, srcR, dstR, paint);
@@ -1001,22 +1010,48 @@
      * <p>This method only returns true if {@link #hasAlpha()} returns true.
      * A bitmap with no alpha channel can be used both as a pre-multiplied and
      * as a non pre-multiplied bitmap.</p>
-     * 
+     *
+     * <p>Only pre-multiplied bitmaps may be drawn by the view system or
+     * {@link Canvas}. If a non-pre-multiplied bitmap with an alpha channel is
+     * drawn to a Canvas, a RuntimeException will be thrown.</p>
+     *
      * @return true if the underlying pixels have been pre-multiplied, false
      *         otherwise
+     *
+     * @see Bitmap#setPremultiplied(boolean)
+     * @see BitmapFactory.Options#inPremultiplied
      */
     public final boolean isPremultiplied() {
-        return getConfig() != Config.RGB_565 && hasAlpha();
+        return mIsPremultiplied && getConfig() != Config.RGB_565 && hasAlpha();
+    }
+
+    /**
+     * Sets whether the bitmap should treat its data as pre-multiplied.
+     *
+     * <p>Bitmaps are always treated as pre-multiplied by the view system and
+     * {@link Canvas} for performance reasons. Storing un-pre-multiplied data in
+     * a Bitmap (through {@link #setPixel}, {@link #setPixels}, or {@link
+     * BitmapFactory.Options#inPremultiplied BitmapFactory.Options.inPremultiplied})
+     * can lead to incorrect blending if drawn by the framework.</p>
+     *
+     * <p>This method will not affect the behavior of a bitmap without an alpha
+     * channel, or if {@link #hasAlpha()} returns false.</p>
+     *
+     * @see Bitmap#isPremultiplied()
+     * @see BitmapFactory.Options#inPremultiplied
+     */
+    public final void setPremultiplied(boolean premultiplied) {
+        mIsPremultiplied = premultiplied;
     }
 
     /** Returns the bitmap's width */
     public final int getWidth() {
-        return mWidth == -1 ? mWidth = nativeWidth(mNativeBitmap) : mWidth;
+        return mWidth;
     }
 
     /** Returns the bitmap's height */
     public final int getHeight() {
-        return mHeight == -1 ? mHeight = nativeHeight(mNativeBitmap) : mHeight;
+        return mHeight;
     }
 
     /**
@@ -1236,7 +1271,7 @@
     public int getPixel(int x, int y) {
         checkRecycled("Can't call getPixel() on a recycled bitmap");
         checkPixelAccess(x, y);
-        return nativeGetPixel(mNativeBitmap, x, y);
+        return nativeGetPixel(mNativeBitmap, x, y, mIsPremultiplied);
     }
 
     /**
@@ -1270,7 +1305,7 @@
         }
         checkPixelsAccess(x, y, width, height, offset, stride, pixels);
         nativeGetPixels(mNativeBitmap, pixels, offset, stride,
-                        x, y, width, height);
+                        x, y, width, height, mIsPremultiplied);
     }
 
     /**
@@ -1350,7 +1385,7 @@
             throw new IllegalStateException();
         }
         checkPixelAccess(x, y);
-        nativeSetPixel(mNativeBitmap, x, y, color);
+        nativeSetPixel(mNativeBitmap, x, y, color, mIsPremultiplied);
     }
 
     /**
@@ -1387,7 +1422,7 @@
         }
         checkPixelsAccess(x, y, width, height, offset, stride, pixels);
         nativeSetPixels(mNativeBitmap, pixels, offset, stride,
-                        x, y, width, height);
+                        x, y, width, height, mIsPremultiplied);
     }
 
     public static final Parcelable.Creator<Bitmap> CREATOR
@@ -1535,21 +1570,20 @@
                                             int quality, OutputStream stream,
                                             byte[] tempStorage);
     private static native void nativeErase(int nativeBitmap, int color);
-    private static native int nativeWidth(int nativeBitmap);
-    private static native int nativeHeight(int nativeBitmap);
     private static native int nativeRowBytes(int nativeBitmap);
     private static native int nativeConfig(int nativeBitmap);
 
-    private static native int nativeGetPixel(int nativeBitmap, int x, int y);
+    private static native int nativeGetPixel(int nativeBitmap, int x, int y,
+                                             boolean isPremultiplied);
     private static native void nativeGetPixels(int nativeBitmap, int[] pixels,
-                                               int offset, int stride, int x,
-                                               int y, int width, int height);
+                                               int offset, int stride, int x, int y,
+                                               int width, int height, boolean isPremultiplied);
 
     private static native void nativeSetPixel(int nativeBitmap, int x, int y,
-                                              int color);
+                                              int color, boolean isPremultiplied);
     private static native void nativeSetPixels(int nativeBitmap, int[] colors,
-                                               int offset, int stride, int x,
-                                               int y, int width, int height);
+                                               int offset, int stride, int x, int y,
+                                               int width, int height, boolean isPremultiplied);
     private static native void nativeCopyPixelsToBuffer(int nativeBitmap,
                                                         Buffer dst);
     private static native void nativeCopyPixelsFromBuffer(int nb, Buffer src);
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index a4124bf..1c426fd 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -44,6 +44,7 @@
         public Options() {
             inDither = false;
             inScaled = true;
+            inPremultiplied = true;
         }
 
         /**
@@ -125,6 +126,26 @@
         public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
 
         /**
+         * If true (which is the default), the resulting bitmap will have its
+         * color channels pre-multipled by the alpha channel.
+         *
+         * <p>This should NOT be set to false for images to be directly drawn by
+         * the view system or through a {@link Canvas}. The view system and
+         * {@link Canvas} assume all drawn images are pre-multiplied to simplify
+         * draw-time blending, and will throw a RuntimeException when
+         * un-premultiplied are drawn.</p>
+         *
+         * <p>This is likely only useful if you want to manipulate raw encoded
+         * image data, e.g. with RenderScript or custom OpenGL.</p>
+         *
+         * <p>This does not affect bitmaps without an alpha channel.</p>
+         *
+         * @see Bitmap#hasAlpha()
+         * @see Bitmap#isPremultiplied()
+         */
+        public boolean inPremultiplied;
+
+        /**
          * If dither is true, the decoder will attempt to dither the decoded
          * image.
          */
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 0ea4074..d46238f 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -136,7 +136,7 @@
         if (!bitmap.isMutable()) {
             throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");
         }
-        throwIfRecycled(bitmap);
+        throwIfCannotDraw(bitmap);
         mNativeCanvas = initRaster(bitmap.ni());
         mFinalizer = new CanvasFinalizer(mNativeCanvas);
         mBitmap = bitmap;
@@ -225,7 +225,7 @@
             if (!bitmap.isMutable()) {
                 throw new IllegalStateException();
             }
-            throwIfRecycled(bitmap);
+            throwIfCannotDraw(bitmap);
 
             safeCanvasSwap(initRaster(bitmap.ni()), true);
             mDensity = bitmap.mDensity;
@@ -1075,11 +1075,19 @@
     public void drawPath(Path path, Paint paint) {
         native_drawPath(mNativeCanvas, path.ni(), paint.mNativePaint);
     }
-    
-    private static void throwIfRecycled(Bitmap bitmap) {
+
+    /**
+     * @hide
+     */
+    protected static void throwIfCannotDraw(Bitmap bitmap) {
         if (bitmap.isRecycled()) {
             throw new RuntimeException("Canvas: trying to use a recycled bitmap " + bitmap);
         }
+        if (!bitmap.isPremultiplied() && bitmap.getConfig() == Bitmap.Config.ARGB_8888 &&
+                bitmap.hasAlpha()) {
+            throw new RuntimeException("Canvas: trying to use a non-premultiplied bitmap "
+                    + bitmap);
+        }
     }
 
     /**
@@ -1128,7 +1136,7 @@
      * @param paint  The paint used to draw the bitmap (may be null)
      */
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
-        throwIfRecycled(bitmap);
+        throwIfCannotDraw(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), left, top,
                 paint != null ? paint.mNativePaint : 0, mDensity, mScreenDensity, bitmap.mDensity);
     }
@@ -1159,7 +1167,7 @@
         if (dst == null) {
             throw new NullPointerException();
         }
-        throwIfRecycled(bitmap);
+        throwIfCannotDraw(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
                           paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
     }
@@ -1190,7 +1198,7 @@
         if (dst == null) {
             throw new NullPointerException();
         }
-        throwIfRecycled(bitmap);
+        throwIfCannotDraw(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
                 paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
     }
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index ef08c29..e023739 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -37,10 +37,11 @@
  * faces. LOD and cube map faces are booleans to indicate present or not
  * present. </p>
  *
- * <p>A Type also supports YUV format information to support an {@link
- * android.renderscript.Allocation} in a YUV format. The YUV formats supported
- * are {@link android.graphics.ImageFormat#YV12} and {@link
- * android.graphics.ImageFormat#NV21}.</p>
+ * <p>A Type also supports YUV format information to support an
+ * {@link android.renderscript.Allocation} in a YUV format. The YUV formats
+ * supported are {@link android.graphics.ImageFormat#YV12},
+ * {@link android.graphics.ImageFormat#NV21}, and
+ * {@link android.graphics.ImageFormat#YUV_420_888}</p>
  *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
@@ -284,16 +285,19 @@
         /**
          * Set the YUV layout for a Type.
          *
-         * @param yuvFormat {@link android.graphics.ImageFormat#YV12} or {@link android.graphics.ImageFormat#NV21}
+         * @param yuvFormat {@link android.graphics.ImageFormat#YV12}, {@link android.graphics.ImageFormat#NV21}, or
+         * {@link android.graphics.ImageFormat#YUV_420_888}.
          */
         public Builder setYuvFormat(int yuvFormat) {
             switch (yuvFormat) {
             case android.graphics.ImageFormat.NV21:
             case android.graphics.ImageFormat.YV12:
+            case android.graphics.ImageFormat.YUV_420_888:
                 break;
 
             default:
-                throw new RSIllegalArgumentException("Only NV21 and YV12 are supported..");
+                throw new RSIllegalArgumentException(
+                    "Only ImageFormat.NV21, .YV12, and .YUV_420_888 are supported..");
             }
 
             mYuv = yuvFormat;
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 328ac5d..9ea325a4 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -443,7 +443,10 @@
             }
             @Override public void onServiceDisconnected(ComponentName name) {}
         };
-        boolean isBound = context.bindService(new Intent(IKeyChainService.class.getName()),
+        Intent intent = new Intent(IKeyChainService.class.getName());
+        ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
+        intent.setComponent(comp);
+        boolean isBound = context.bindService(intent,
                                               keyChainServiceConnection,
                                               Context.BIND_AUTO_CREATE);
         if (!isBound) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index c0b3bfc..f8d35891 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -166,11 +166,16 @@
         debugLayersUpdates = false;
     }
 
+    debugOverdraw = false;
     if (property_get(PROPERTY_DEBUG_OVERDRAW, property, NULL) > 0) {
         INIT_LOGD("  Overdraw debug enabled: %s", property);
-        debugOverdraw = !strcmp(property, "show");
-    } else {
-        debugOverdraw = false;
+        if (!strcmp(property, "show")) {
+            debugOverdraw = true;
+            mOverdrawDebugColorSet = kColorSet_Default;
+        } else if (!strcmp(property, "show_deuteranomaly")) {
+            debugOverdraw = true;
+            mOverdrawDebugColorSet = kColorSet_Deuteranomaly;
+        }
     }
 
     // See Properties.h for valid values
@@ -235,6 +240,16 @@
 // Debug
 ///////////////////////////////////////////////////////////////////////////////
 
+uint32_t Caches::getOverdrawColor(uint32_t amount) const {
+    static uint32_t sOverdrawColors[2][4] = {
+            { 0x2f0000ff, 0x2f00ff00, 0x3fff0000, 0x7fff0000 },
+            { 0x2f0000ff, 0x4fffff00, 0x5fff8ad8, 0x7fff0000 }
+    };
+    if (amount < 1) amount = 1;
+    if (amount > 4) amount = 4;
+    return sOverdrawColors[mOverdrawDebugColorSet][amount - 1];
+}
+
 void Caches::dumpMemoryUsage() {
     String8 stringLog;
     dumpMemoryUsage(stringLog);
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index f8b1e17..282aee9 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -150,6 +150,12 @@
     }
 
     /**
+     * Returns a non-premultiplied ARGB color for the specified
+     * amount of overdraw (1 for 1x, 2 for 2x, etc.)
+     */
+    uint32_t getOverdrawColor(uint32_t amount) const;
+
+    /**
      * Call this on each frame to ensure that garbage is deleted from
      * GPU memory.
      */
@@ -348,6 +354,11 @@
     PFNGLGETOBJECTLABELEXTPROC getLabel;
 
 private:
+    enum OverdrawColorSet {
+        kColorSet_Default = 0,
+        kColorSet_Deuteranomaly
+    };
+
     void initFont();
     void initExtensions();
     void initConstraints();
@@ -400,6 +411,8 @@
     uint32_t mFunctorsCount;
 
     GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
+
+    OverdrawColorSet mOverdrawDebugColorSet;
 }; // class Caches
 
 }; // namespace uirenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index cb6bb2e..22b1485 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -737,7 +737,7 @@
             }
 
             mRsElement = RSC::Element::A_8(mRs);
-            mRsScript = new RSC::ScriptIntrinsicBlur(mRs, mRsElement);
+            mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
         }
 
         RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
@@ -749,7 +749,8 @@
                 outImage);
 
         mRsScript->setRadius(radius);
-        mRsScript->blur(ain, aout);
+        mRsScript->setInput(ain);
+        mRsScript->forEach(aout);
 
         // replace the original image's pointer, avoiding a copy back to the original buffer
         free(*image);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 707f662..f2352bb 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -530,14 +530,22 @@
         mCaches.setScissor(clip->left, mFirstSnapshot->height - clip->bottom,
                 clip->right - clip->left, clip->bottom - clip->top);
 
+        // 1x overdraw
         mCaches.stencil.enableDebugTest(2);
-        drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
+        drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
+
+        // 2x overdraw
         mCaches.stencil.enableDebugTest(3);
-        drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
+        drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
+
+        // 3x overdraw
         mCaches.stencil.enableDebugTest(4);
-        drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
+        drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
+
+        // 4x overdraw and higher
         mCaches.stencil.enableDebugTest(4, true);
-        drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
+        drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
+
         mCaches.stencil.disable();
     }
 }
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 70ab6e7..5df6408 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -214,7 +214,22 @@
 void PathCache::removeTexture(PathTexture* texture) {
     if (texture) {
         const uint32_t size = texture->width * texture->height;
-        mSize -= size;
+
+        // If there is a pending task we must wait for it to return
+        // before attempting our cleanup
+        const sp<Task<SkBitmap*> >& task = texture->task();
+        if (task != NULL) {
+            SkBitmap* bitmap = task->getResult();
+            texture->clearTask();
+        } else {
+            // If there is a pending task, the path was not added
+            // to the cache and the size wasn't increased
+            if (size > mSize) {
+                ALOGE("Removing path texture of size %d will leave "
+                        "the cache in an inconsistent state", size);
+            }
+            mSize -= size;
+        }
 
         PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d",
                 texture->id, size, mSize);
@@ -283,6 +298,11 @@
             mCache.put(entry, texture);
         }
     } else {
+        // It's okay to add a texture that's bigger than the cache since
+        // we'll trim the cache later when addToCache is set to false
+        if (!addToCache) {
+            mSize += size;
+        }
         texture->cleanup = true;
     }
 }
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 86b0aa2..20b8f2f 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -70,8 +70,15 @@
 #define PROPERTY_DEBUG_LAYERS_UPDATES "debug.hwui.show_layers_updates"
 
 /**
- * Used to enable/disable overdraw debugging. The accepted values are
- * "show", "count" and "false". The default value is "false".
+ * Used to enable/disable overdraw debugging.
+ *
+ * The accepted values are
+ * "show", to show overdraw
+ * "show_deuteranomaly", to show overdraw if you suffer from Deuteranomaly
+ * "count", to show an overdraw counter
+ * "false", to disable overdraw debugging
+ *
+ * The default value is "false".
  */
 #define PROPERTY_DEBUG_OVERDRAW "debug.hwui.overdraw"
 
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index c8bfd9c..189895c 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -29,7 +29,7 @@
 
 TaskManager::TaskManager() {
     // Get the number of available CPUs. This value does not change over time.
-    int cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
+    int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
 
     for (int i = 0; i < cpuCount / 2; i++) {
         String8 name;
diff --git a/location/java/android/location/SettingInjectorService.java b/location/java/android/location/SettingInjectorService.java
index d410408..4bfa150 100644
--- a/location/java/android/location/SettingInjectorService.java
+++ b/location/java/android/location/SettingInjectorService.java
@@ -69,6 +69,11 @@
  *     to the user that it is not part of the system settings.</li>
  * </ul>
  *
+ * To ensure a good user experience, your {@link #onHandleIntent(Intent)} must complete within
+ * 200 msec even if your app is not already running. This means that both
+ * {@link android.app.Application#onCreate()} and {@link #getStatus()} must be fast. If you exceed
+ * this time, then this can delay the retrieval of settings status for other apps as well.
+ *
  * For consistency, the label and {@link #getStatus()} values should be provided in all of the
  * locales supported by the system settings app. The text should not contain offensive language.
  *
@@ -82,6 +87,7 @@
  */
 // TODO: is there a public list of supported locales?
 // TODO: is there a public list of guidelines for settings text?
+// TODO: would a bound service be better? E.g., we could just disconnect if a service took too long
 public abstract class SettingInjectorService extends IntentService {
 
     /**
@@ -106,6 +112,12 @@
      */
     public static final String MESSENGER_KEY = "messenger";
 
+    /**
+     * Intent action a client should broadcast when the value of one of its injected settings has
+     * changed, so that the setting can be updated in the UI.
+     */
+    public static final String UPDATE_INTENT = "com.android.location.InjectedSettingChanged";
+
     private final String mLogTag;
 
     /**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1b9043a..1dcf0e92 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1316,19 +1316,6 @@
     }
 
     /**
-     * @hide
-     * Signals whether remote submix audio rerouting is enabled.
-     */
-    public void setRemoteSubmixOn(boolean on, int address) {
-        IAudioService service = getService();
-        try {
-            service.setRemoteSubmixOn(on, address);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setRemoteSubmixOn", e);
-        }
-    }
-
-    /**
      * Sets audio routing to the wired headset on or off.
      *
      * @param on set <var>true</var> to route audio to/from wired
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 7269f0c..b72551a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -140,24 +140,22 @@
     private static final int MSG_PERSIST_MASTER_VOLUME = 2;
     private static final int MSG_PERSIST_RINGER_MODE = 3;
     private static final int MSG_MEDIA_SERVER_DIED = 4;
-    private static final int MSG_MEDIA_SERVER_STARTED = 5;
-    private static final int MSG_PLAY_SOUND_EFFECT = 6;
-    private static final int MSG_BTA2DP_DOCK_TIMEOUT = 7;
-    private static final int MSG_LOAD_SOUND_EFFECTS = 8;
-    private static final int MSG_SET_FORCE_USE = 9;
-    private static final int MSG_BT_HEADSET_CNCT_FAILED = 10;
-    private static final int MSG_SET_ALL_VOLUMES = 11;
-    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 12;
-    private static final int MSG_REPORT_NEW_ROUTES = 13;
-    private static final int MSG_SET_FORCE_BT_A2DP_USE = 14;
-    private static final int MSG_SET_RSX_CONNECTION_STATE = 15; // change remote submix connection
-    private static final int MSG_CHECK_MUSIC_ACTIVE = 16;
-    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 17;
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 18;
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 19;
-    private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 20;
-    private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 21;
-    private static final int MSG_UNLOAD_SOUND_EFFECTS = 22;
+    private static final int MSG_PLAY_SOUND_EFFECT = 5;
+    private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
+    private static final int MSG_LOAD_SOUND_EFFECTS = 7;
+    private static final int MSG_SET_FORCE_USE = 8;
+    private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
+    private static final int MSG_SET_ALL_VOLUMES = 10;
+    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
+    private static final int MSG_REPORT_NEW_ROUTES = 12;
+    private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
+    private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
+    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17;
+    private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
+    private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
+    private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -181,8 +179,6 @@
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
 
-    private boolean mMediaServerOk;
-
     private SoundPool mSoundPool;
     private final Object mSoundEffectsLock = new Object();
     private static final int NUM_SOUNDPOOL_CHANNELS = 4;
@@ -287,23 +283,13 @@
         public void onError(int error) {
             switch (error) {
             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
-                if (mMediaServerOk) {
-                    sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
-                            null, 1500);
-                    mMediaServerOk = false;
-                }
-                break;
-            case AudioSystem.AUDIO_STATUS_OK:
-                if (!mMediaServerOk) {
-                    sendMsg(mAudioHandler, MSG_MEDIA_SERVER_STARTED, SENDMSG_NOOP, 0, 0,
-                            null, 0);
-                    mMediaServerOk = true;
-                }
+                sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED,
+                        SENDMSG_NOOP, 0, 0, null, 0);
                 break;
             default:
                 break;
             }
-       }
+        }
     };
 
     /**
@@ -500,6 +486,8 @@
         mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(),
                 mContext, /*VolumeController*/ mVolumePanel, this);
 
+        AudioSystem.setErrorCallback(mAudioSystemCallback);
+
         boolean cameraSoundForced = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_camera_sound_forced);
         mCameraSoundForced = new Boolean(cameraSoundForced);
@@ -529,15 +517,12 @@
         createStreamStates();
 
         readAndSetLowRamDevice();
-        mMediaServerOk = true;
 
         // Call setRingerModeInt() to apply correct mute
         // state on streams affected by ringer mode.
         mRingerModeMutedStreams = 0;
         setRingerModeInt(getRingerMode(), false);
 
-        AudioSystem.setErrorCallback(mAudioSystemCallback);
-
         // Register for device connection intent broadcasts.
         IntentFilter intentFilter =
                 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
@@ -1927,7 +1912,16 @@
         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
             return;
         }
-        mForcedUseForComm = on ? AudioSystem.FORCE_SPEAKER : AudioSystem.FORCE_NONE;
+
+        if (on) {
+            if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
+                    sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
+                            AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);
+            }
+            mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
+        } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
+            mForcedUseForComm = AudioSystem.FORCE_NONE;
+        }
 
         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
@@ -1943,7 +1937,12 @@
         if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
             return;
         }
-        mForcedUseForComm = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
+
+        if (on) {
+            mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
+        } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
+            mForcedUseForComm = AudioSystem.FORCE_NONE;
+        }
 
         sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
                 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
@@ -2393,26 +2392,6 @@
         }
     };
 
-    /** see AudioManager.setRemoteSubmixOn(boolean on) */
-    public void setRemoteSubmixOn(boolean on, int address) {
-        sendMsg(mAudioHandler, MSG_SET_RSX_CONNECTION_STATE,
-                SENDMSG_REPLACE /* replace with QUEUE when multiple addresses are supported */,
-                on ? 1 : 0 /*arg1*/,
-                address /*arg2*/,
-                null/*obj*/, 0/*delay*/);
-    }
-
-    private void onSetRsxConnectionState(int available, int address) {
-        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_REMOTE_SUBMIX,
-                available == 1 ?
-                        AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                String.valueOf(address) /*device_address*/);
-        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX,
-                available == 1 ?
-                        AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                String.valueOf(address) /*device_address*/);
-    }
-
     private void onCheckMusicActive() {
         synchronized (mSafeMediaVolumeState) {
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
@@ -3453,21 +3432,17 @@
                     break;
 
                 case MSG_MEDIA_SERVER_DIED:
-                    if (!mMediaServerOk) {
+                    if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) {
                         Log.e(TAG, "Media server died.");
-                        // Force creation of new IAudioFlinger interface so that we are notified
-                        // when new media_server process is back to life.
-                        AudioSystem.setErrorCallback(mAudioSystemCallback);
                         sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
                                 null, 500);
+                        break;
                     }
-                    break;
-
-                case MSG_MEDIA_SERVER_STARTED:
                     Log.e(TAG, "Media server started.");
+
                     // indicate to audio HAL that we start the reconfiguration phase after a media
                     // server crash
-                    // Note that MSG_MEDIA_SERVER_STARTED message is only received when the media server
+                    // Note that we only execute this when the media server
                     // process restarts after a crash, not the first time it is started.
                     AudioSystem.setParameters("restarting=true");
 
@@ -3600,10 +3575,6 @@
                     break;
                 }
 
-                case MSG_SET_RSX_CONNECTION_STATE:
-                    onSetRsxConnectionState(msg.arg1/*available*/, msg.arg2/*address*/);
-                    break;
-
                 case MSG_CHECK_MUSIC_ACTIVE:
                     onCheckMusicActive();
                     break;
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 4805da5..661b0fd 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -177,12 +177,10 @@
     {
         synchronized (AudioSystem.class) {
             mErrorCallback = cb;
+            if (cb != null) {
+                cb.onError(checkAudioFlinger());
+            }
         }
-        // Calling a method on AudioFlinger here makes sure that we bind to IAudioFlinger
-        // binder interface death. Not doing that would result in not being notified of
-        // media_server process death if no other method is called on AudioSystem that reaches
-        // to AudioFlinger.
-        isMicrophoneMuted();
     }
 
     private static void errorCallbackFromNative(int error)
@@ -404,5 +402,5 @@
     public static native int getOutputLatency(int stream);
 
     public static native int setLowRamDevice(boolean isLowRamDevice);
-
+    public static native int checkAudioFlinger();
 }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index c7a749a..fe060f8 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -114,8 +114,6 @@
 
     boolean isBluetoothA2dpOn();
 
-    oneway void setRemoteSubmixOn(boolean on, int address);
-
     int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb,
             IAudioFocusDispatcher fd, String clientId, String callingPackageName);
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 241c7fac..946dd71 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -38,6 +38,8 @@
 import android.graphics.Bitmap;
 import android.graphics.SurfaceTexture;
 import android.media.AudioManager;
+import android.media.MediaFormat;
+import android.media.SubtitleData;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -1335,6 +1337,7 @@
         mOnInfoListener = null;
         mOnVideoSizeChangedListener = null;
         mOnTimedTextListener = null;
+        mOnSubtitleDataListener = null;
         _release();
     }
 
@@ -1526,20 +1529,43 @@
          * ISO-639-2 language code, "und", is returned.
          */
         public String getLanguage() {
-            return mLanguage;
+            String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
+            return language == null ? "und" : language;
+        }
+
+        /**
+         * Gets the {@link MediaFormat} of the track.  If the format is
+         * unknown or could not be determined, null is returned.
+         */
+        public MediaFormat getFormat() {
+            if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
+                return mFormat;
+            }
+            return null;
         }
 
         public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0;
         public static final int MEDIA_TRACK_TYPE_VIDEO = 1;
         public static final int MEDIA_TRACK_TYPE_AUDIO = 2;
         public static final int MEDIA_TRACK_TYPE_TIMEDTEXT = 3;
+        /** @hide */
+        public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4;
 
         final int mTrackType;
-        final String mLanguage;
+        final MediaFormat mFormat;
 
         TrackInfo(Parcel in) {
             mTrackType = in.readInt();
-            mLanguage = in.readString();
+            // TODO: parcel in the full MediaFormat
+            String language = in.readString();
+
+            if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
+                mFormat = MediaFormat.createSubtitleFormat(
+                    MEDIA_MIMETYPE_TEXT_SUBRIP, language);
+            } else {
+                mFormat = new MediaFormat();
+                mFormat.setString(MediaFormat.KEY_LANGUAGE, language);
+            }
         }
 
         /**
@@ -1556,7 +1582,7 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mTrackType);
-            dest.writeString(mLanguage);
+            dest.writeString(getLanguage());
         }
 
         /**
@@ -1891,6 +1917,7 @@
     private static final int MEDIA_TIMED_TEXT = 99;
     private static final int MEDIA_ERROR = 100;
     private static final int MEDIA_INFO = 200;
+    private static final int MEDIA_SUBTITLE_DATA = 201;
 
     private class EventHandler extends Handler
     {
@@ -1970,6 +1997,18 @@
                 }
                 return;
 
+            case MEDIA_SUBTITLE_DATA:
+                if (mOnSubtitleDataListener == null) {
+                    return;
+                }
+                if (msg.obj instanceof Parcel) {
+                    Parcel parcel = (Parcel) msg.obj;
+                    SubtitleData data = new SubtitleData(parcel);
+                    parcel.recycle();
+                    mOnSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+                }
+                return;
+
             case MEDIA_NOP: // interface test message - ignore
                 break;
 
@@ -2181,6 +2220,30 @@
 
     private OnTimedTextListener mOnTimedTextListener;
 
+    /**
+     * Interface definition of a callback to be invoked when a
+     * track has data available.
+     *
+     * @hide
+     */
+    public interface OnSubtitleDataListener
+    {
+        public void onSubtitleData(MediaPlayer mp, SubtitleData data);
+    }
+
+    /**
+     * Register a callback to be invoked when a track has data available.
+     *
+     * @param listener the callback that will be run
+     *
+     * @hide
+     */
+    public void setOnSubtitleDataListener(OnSubtitleDataListener listener)
+    {
+        mOnSubtitleDataListener = listener;
+    }
+
+    private OnSubtitleDataListener mOnSubtitleDataListener;
 
     /* Do not change these values without updating their counterparts
      * in include/media/mediaplayer.h!
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 3e688db..1d2b889 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -179,6 +179,27 @@
          *  is applied.
          */
         public static final int VOICE_COMMUNICATION = 7;
+
+        /**
+         * Audio source for a submix of audio streams to be presented remotely.
+         * <p>
+         * An application can use this audio source to capture a mix of audio streams
+         * that should be transmitted to a remote receiver such as a Wifi display.
+         * While recording is active, these audio streams are redirected to the remote
+         * submix instead of being played on the device speaker or headset.
+         * </p><p>
+         * Certain streams are excluded from the remote submix, including
+         * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_ALARM},
+         * and {@link AudioManager#STREAM_NOTIFICATION}.  These streams will continue
+         * to be presented locally as usual.
+         * </p><p>
+         * Capturing the remote submix audio requires the
+         * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
+         * This permission is reserved for use by system components and is not available to
+         * third-party applications.
+         * </p>
+         */
+        public static final int REMOTE_SUBMIX = 8;
     }
 
     /**
@@ -294,7 +315,7 @@
      * @see android.media.MediaRecorder.AudioSource
      */
     public static final int getAudioSourceMax() {
-        return AudioSource.VOICE_COMMUNICATION;
+        return AudioSource.REMOTE_SUBMIX;
     }
 
     /**
diff --git a/media/java/android/media/SubtitleData.java b/media/java/android/media/SubtitleData.java
new file mode 100644
index 0000000..f552e82
--- /dev/null
+++ b/media/java/android/media/SubtitleData.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 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.media;
+
+import android.os.Parcel;
+import android.util.Log;
+
+/**
+ * @hide
+ *
+ * Class to hold the subtitle track's data, including:
+ * <ul>
+ * <li> Track index</li>
+ * <li> Start time (in microseconds) of the data</li>
+ * <li> Duration (in microseconds) of the data</li>
+ * <li> A byte-array of the data</li>
+ * </ul>
+ *
+ * <p> To receive the subtitle data, applications need to do the following:
+ *
+ * <ul>
+ * <li> Select a track of type MEDIA_TRACK_TYPE_SUBTITLE with {@link MediaPlayer.selectTrack(int)</li>
+ * <li> Implement the {@link MediaPlayer.OnSubtitleDataListener} interface</li>
+ * <li> Register the {@link MediaPlayer.OnSubtitleDataListener} callback on a MediaPlayer object</li>
+ * </ul>
+ *
+ * @see android.media.MediaPlayer
+ */
+public final class SubtitleData
+{
+    private static final String TAG = "SubtitleData";
+
+    private int mTrackIndex;
+    private long mStartTimeUs;
+    private long mDurationUs;
+    private byte[] mData;
+
+    public SubtitleData(Parcel parcel) {
+        if (!parseParcel(parcel)) {
+            throw new IllegalArgumentException("parseParcel() fails");
+        }
+    }
+
+    public int getTrackIndex() {
+        return mTrackIndex;
+    }
+
+    public long getStartTimeUs() {
+        return mStartTimeUs;
+    }
+
+    public long getDurationUs() {
+        return mDurationUs;
+    }
+
+    public byte[] getData() {
+        return mData;
+    }
+
+    private boolean parseParcel(Parcel parcel) {
+        parcel.setDataPosition(0);
+        if (parcel.dataAvail() == 0) {
+            return false;
+        }
+
+        mTrackIndex = parcel.readInt();
+        mStartTimeUs = parcel.readLong();
+        mDurationUs = parcel.readLong();
+        mData = new byte[parcel.readInt()];
+        parcel.readByteArray(mData);
+
+        return true;
+    }
+}
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 5225e23..722087c 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -18,7 +18,7 @@
 
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CameraPropertiesKeys;
+import android.hardware.camera2.CameraProperties;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
@@ -271,7 +271,7 @@
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
         assertFalse(info.isEmpty());
-        assertNotNull(info.get(CameraPropertiesKeys.Scaler.AVAILABLE_FORMATS));
+        assertNotNull(info.get(CameraProperties.SCALER_AVAILABLE_FORMATS));
     }
 
     @SmallTest
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 074bfe48..2d26ac7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -86,9 +86,9 @@
     private Writer mProcMemWriter;
     private Writer mMemWriter;
 
-    private CamcorderProfile mCamcorderProfile = CamcorderProfile.get(CAMERA_ID);
-    private int mVideoWidth = mCamcorderProfile.videoFrameWidth;
-    private int mVideoHeight = mCamcorderProfile.videoFrameHeight;
+    private CamcorderProfile mCamcorderProfile;
+    private int mVideoWidth;
+    private int mVideoHeight;
 
     Camera mCamera;
 
@@ -99,6 +99,12 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        //Check if the device support the camcorder
+        CamcorderProfile mCamcorderProfile = CamcorderProfile.get(CAMERA_ID);
+        if (mCamcorderProfile != null) {
+            mVideoWidth = mCamcorderProfile.videoFrameWidth;
+            mVideoHeight = mCamcorderProfile.videoFrameHeight;
+        }
         //Insert a 2 second before launching the test activity. This is
         //the workaround for the race condition of requesting the updated surface.
         Thread.sleep(2000);
@@ -332,7 +338,7 @@
         // USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
         // media     131   1     13676  4796  ffffffff 400b1bd0 S media.log
         // media     219   131   37768  6892  ffffffff 400b236c S /system/bin/mediaserver
-        String memusage = poList[2].concat("\n");
+        String memusage = poList[poList.length-1].concat("\n");
         return memusage;
     }
 
@@ -410,59 +416,65 @@
     // Test case 4: Capture the memory usage after every 20 video only recorded
     @LargeTest
     public void testH263RecordVideoOnlyMemoryUsage() throws Exception {
-        boolean memoryResult = false;
-        mStartPid = getMediaserverPid();
-        int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
-        assertTrue("H263 video recording frame rate", frameRate != -1);
-        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
-            assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
-                    MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4,
-                    MediaNames.RECORDED_VIDEO_3GP, true));
-            getMemoryWriteToLog(i);
-            writeProcmemInfo();
+        if (mCamcorderProfile != null) {
+            boolean memoryResult = false;
+            mStartPid = getMediaserverPid();
+            int frameRate = MediaProfileReader
+                    .getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
+            assertTrue("H263 video recording frame rate", frameRate != -1);
+            for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+                assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
+                        MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4,
+                        MediaNames.RECORDED_VIDEO_3GP, true));
+                getMemoryWriteToLog(i);
+                writeProcmemInfo();
+            }
+            memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
+            assertTrue("H263 record only memory test", memoryResult);
         }
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
-        assertTrue("H263 record only memory test", memoryResult);
     }
 
     // Test case 5: Capture the memory usage after every 20 video only recorded
     @LargeTest
     public void testMpeg4RecordVideoOnlyMemoryUsage() throws Exception {
-        boolean memoryResult = false;
-
-        mStartPid = getMediaserverPid();
-        int frameRate = MediaProfileReader.getMaxFrameRateForCodec
-                (MediaRecorder.VideoEncoder.MPEG_4_SP);
-        assertTrue("MPEG4 video recording frame rate", frameRate != -1);
-        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
-            assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
-                    MediaRecorder.VideoEncoder.MPEG_4_SP, MediaRecorder.OutputFormat.MPEG_4,
-                    MediaNames.RECORDED_VIDEO_3GP, true));
-            getMemoryWriteToLog(i);
-            writeProcmemInfo();
+        if (mCamcorderProfile != null) {
+            boolean memoryResult = false;
+            mStartPid = getMediaserverPid();
+            int frameRate = MediaProfileReader.getMaxFrameRateForCodec
+                    (MediaRecorder.VideoEncoder.MPEG_4_SP);
+            assertTrue("MPEG4 video recording frame rate", frameRate != -1);
+            for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+                assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
+                        MediaRecorder.VideoEncoder.MPEG_4_SP, MediaRecorder.OutputFormat.MPEG_4,
+                        MediaNames.RECORDED_VIDEO_3GP, true));
+                getMemoryWriteToLog(i);
+                writeProcmemInfo();
+            }
+            memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
+            assertTrue("mpeg4 record only memory test", memoryResult);
         }
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
-        assertTrue("mpeg4 record only memory test", memoryResult);
     }
 
     // Test case 6: Capture the memory usage after every 20 video and audio
     // recorded
     @LargeTest
     public void testRecordVideoAudioMemoryUsage() throws Exception {
-        boolean memoryResult = false;
-
-        mStartPid = getMediaserverPid();
-        int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
-        assertTrue("H263 video recording frame rate", frameRate != -1);
-        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
-            assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
-                    MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4,
-                    MediaNames.RECORDED_VIDEO_3GP, false));
-            getMemoryWriteToLog(i);
-            writeProcmemInfo();
+        if (mCamcorderProfile != null) {
+            boolean memoryResult = false;
+            mStartPid = getMediaserverPid();
+            int frameRate = MediaProfileReader
+                    .getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
+            assertTrue("H263 video recording frame rate", frameRate != -1);
+            for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+                assertTrue(stressVideoRecord(frameRate, mVideoWidth, mVideoHeight,
+                        MediaRecorder.VideoEncoder.H263, MediaRecorder.OutputFormat.MPEG_4,
+                        MediaNames.RECORDED_VIDEO_3GP, false));
+                getMemoryWriteToLog(i);
+                writeProcmemInfo();
+            }
+            memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
+            assertTrue("H263 audio video record memory test", memoryResult);
         }
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
-        assertTrue("H263 audio video record memory test", memoryResult);
     }
 
     // Test case 7: Capture the memory usage after every 20 audio only recorded
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 518dcdc..d79f5c6 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -4,6 +4,7 @@
     <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
 
     <application
+        android:name=".DocumentsApplication"
         android:label="@string/app_label"
         android:supportsRtl="true">
 
@@ -51,6 +52,14 @@
             android:authorities="com.android.documentsui.recents"
             android:exported="false" />
 
+        <receiver android:name=".DocumentChangedReceiver">
+            <intent-filter>
+                <action android:name="android.provider.action.DOCUMENT_CHANGED" />
+                <data android:mimeType="vnd.android.cursor.dir/root" />
+                <data android:mimeType="vnd.android.cursor.item/root" />
+            </intent-filter>
+        </receiver>
+
         <!-- TODO: remove when we have real clients -->
         <activity android:name=".TestActivity" android:enabled="false">
             <intent-filter>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 8dbd1de..67c5954 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -42,4 +42,12 @@
         android:paddingStart="?android:attr/listPreferredItemPaddingStart"
         android:visibility="gone" />
 
+    <Button
+        android:id="@+id/more"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
+        android:text="@string/more"
+        android:visibility="gone" />
+
 </FrameLayout>
diff --git a/packages/DocumentsUI/res/menu/mode_directory.xml b/packages/DocumentsUI/res/menu/mode_directory.xml
index 6b6d7e91..624e0247 100644
--- a/packages/DocumentsUI/res/menu/mode_directory.xml
+++ b/packages/DocumentsUI/res/menu/mode_directory.xml
@@ -19,4 +19,14 @@
         android:id="@+id/menu_open"
         android:title="@string/menu_open"
         android:showAsAction="always" />
+    <item
+        android:id="@+id/menu_share"
+        android:icon="@android:drawable/ic_menu_share"
+        android:title="@string/menu_share"
+        android:showAsAction="always" />
+    <item
+        android:id="@+id/menu_delete"
+        android:icon="@android:drawable/ic_menu_delete"
+        android:title="@string/menu_delete"
+        android:showAsAction="always" />
 </menu>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 760f99b..928ba85 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -29,6 +29,8 @@
 
     <string name="menu_open">Open</string>
     <string name="menu_save">Save</string>
+    <string name="menu_share">Share</string>
+    <string name="menu_delete">Delete</string>
 
     <string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string>
 
@@ -55,4 +57,10 @@
 
     <string name="empty">No items</string>
 
+    <string name="toast_no_application">Can\'t open file</string>
+    <string name="toast_failed_delete">Unable to delete some documents</string>
+
+    <string name="more">More</string>
+    <string name="loading">Loading\u2026</string>
+
 </resources>
diff --git a/packages/DocumentsUI/res/xml/document_provider.xml b/packages/DocumentsUI/res/xml/document_provider.xml
new file mode 100644
index 0000000..77891cb
--- /dev/null
+++ b/packages/DocumentsUI/res/xml/document_provider.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<documents-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:customRoots="true">
+</documents-provider>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index fbdb3a7..dd9aee5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -17,13 +17,22 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_MANAGE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_GRID;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_LIST;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_DATE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_NAME;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_SIZE;
 
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.app.LoaderManager.LoaderCallbacks;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
 import android.content.Loader;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.net.Uri;
@@ -46,10 +55,12 @@
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
+import android.widget.Button;
 import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.android.documentsui.DocumentsActivity.DisplayState;
 import com.android.documentsui.model.Document;
@@ -57,7 +68,6 @@
 import com.android.internal.util.Predicate;
 import com.google.android.collect.Lists;
 
-import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
@@ -71,6 +81,7 @@
     private View mEmptyView;
     private ListView mListView;
     private GridView mGridView;
+    private Button mMoreView;
 
     private AbsListView mCurrentView;
 
@@ -85,7 +96,7 @@
     private Point mThumbSize;
 
     private DocumentsAdapter mAdapter;
-    private LoaderCallbacks<List<Document>> mCallbacks;
+    private LoaderCallbacks<DirectoryResult> mCallbacks;
 
     private static final String EXTRA_TYPE = "type";
     private static final String EXTRA_URI = "uri";
@@ -142,14 +153,16 @@
         mGridView.setOnItemClickListener(mItemListener);
         mGridView.setMultiChoiceModeListener(mMultiListener);
 
+        mMoreView = (Button) view.findViewById(R.id.more);
+
         mAdapter = new DocumentsAdapter();
 
         final Uri uri = getArguments().getParcelable(EXTRA_URI);
         mType = getArguments().getInt(EXTRA_TYPE);
 
-        mCallbacks = new LoaderCallbacks<List<Document>>() {
+        mCallbacks = new LoaderCallbacks<DirectoryResult>() {
             @Override
-            public Loader<List<Document>> onCreateLoader(int id, Bundle args) {
+            public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
                 final DisplayState state = getDisplayState(DirectoryFragment.this);
                 mFilter = new MimePredicate(state.acceptMimes);
 
@@ -167,11 +180,11 @@
                 }
 
                 final Comparator<Document> sortOrder;
-                if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
+                if (state.sortOrder == SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
                     sortOrder = new Document.DateComparator();
-                } else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) {
+                } else if (state.sortOrder == SORT_ORDER_NAME) {
                     sortOrder = new Document.NameComparator();
-                } else if (state.sortOrder == DisplayState.SORT_ORDER_SIZE) {
+                } else if (state.sortOrder == SORT_ORDER_SIZE) {
                     sortOrder = new Document.SizeComparator();
                 } else {
                     throw new IllegalArgumentException("Unknown sort order " + state.sortOrder);
@@ -181,12 +194,34 @@
             }
 
             @Override
-            public void onLoadFinished(Loader<List<Document>> loader, List<Document> data) {
-                mAdapter.swapDocuments(data);
+            public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
+                mAdapter.swapDocuments(result.contents);
+
+                final Cursor cursor = result.cursor;
+                if (cursor != null && cursor.getExtras()
+                        .getBoolean(DocumentsContract.EXTRA_HAS_MORE, false)) {
+                    mMoreView.setText(R.string.more);
+                    mMoreView.setVisibility(View.VISIBLE);
+                    mMoreView.setOnClickListener(new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            mMoreView.setText(R.string.loading);
+                            final Bundle bundle = new Bundle();
+                            bundle.putBoolean(DocumentsContract.EXTRA_REQUEST_MORE, true);
+                            try {
+                                cursor.respond(bundle);
+                            } catch (Exception e) {
+                                Log.w(TAG, "Failed to respond: " + e);
+                            }
+                        }
+                    });
+                } else {
+                    mMoreView.setVisibility(View.GONE);
+                }
             }
 
             @Override
-            public void onLoaderReset(Loader<List<Document>> loader) {
+            public void onLoaderReset(Loader<DirectoryResult> loader) {
                 mAdapter.swapDocuments(null);
             }
         };
@@ -216,8 +251,8 @@
         mListView.smoothScrollToPosition(0);
         mGridView.smoothScrollToPosition(0);
 
-        mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE);
-        mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE);
+        mListView.setVisibility(state.mode == MODE_LIST ? View.VISIBLE : View.GONE);
+        mGridView.setVisibility(state.mode == MODE_GRID ? View.VISIBLE : View.GONE);
 
         final int choiceMode;
         if (state.allowMultiple) {
@@ -227,7 +262,7 @@
         }
 
         final int thumbSize;
-        if (state.mode == DisplayState.MODE_GRID) {
+        if (state.mode == MODE_GRID) {
             thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
             mListView.setAdapter(null);
             mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -236,7 +271,7 @@
             mGridView.setNumColumns(GridView.AUTO_FIT);
             mGridView.setChoiceMode(choiceMode);
             mCurrentView = mGridView;
-        } else if (state.mode == DisplayState.MODE_LIST) {
+        } else if (state.mode == MODE_LIST) {
             thumbSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
             mGridView.setAdapter(null);
             mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -269,26 +304,45 @@
 
         @Override
         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+            final DisplayState state = getDisplayState(DirectoryFragment.this);
+
+            final MenuItem open = menu.findItem(R.id.menu_open);
+            final MenuItem share = menu.findItem(R.id.menu_share);
+            final MenuItem delete = menu.findItem(R.id.menu_delete);
+
+            final boolean manageMode = state.action == ACTION_MANAGE;
+            open.setVisible(!manageMode);
+            share.setVisible(manageMode);
+            delete.setVisible(manageMode);
+
             return true;
         }
 
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-            if (item.getItemId() == R.id.menu_open) {
-                final Uri uri = getArguments().getParcelable(EXTRA_URI);
-                final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions();
-                final ArrayList<Document> docs = Lists.newArrayList();
-
-                final int size = checked.size();
-                for (int i = 0; i < size; i++) {
-                    if (checked.valueAt(i)) {
-                        final Document doc = mAdapter.getItem(checked.keyAt(i));
-                        docs.add(doc);
-                    }
+            final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions();
+            final ArrayList<Document> docs = Lists.newArrayList();
+            final int size = checked.size();
+            for (int i = 0; i < size; i++) {
+                if (checked.valueAt(i)) {
+                    final Document doc = mAdapter.getItem(checked.keyAt(i));
+                    docs.add(doc);
                 }
+            }
 
-                ((DocumentsActivity) getActivity()).onDocumentsPicked(docs);
+            final int id = item.getItemId();
+            if (id == R.id.menu_open) {
+                DocumentsActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
                 return true;
+
+            } else if (id == R.id.menu_share) {
+                onShareDocuments(docs);
+                return true;
+
+            } else if (id == R.id.menu_delete) {
+                onDeleteDocuments(docs);
+                return true;
+
             } else {
                 return false;
             }
@@ -315,6 +369,58 @@
         }
     };
 
+    private void onShareDocuments(List<Document> docs) {
+        final ArrayList<Uri> uris = Lists.newArrayList();
+        for (Document doc : docs) {
+            uris.add(doc.uri);
+        }
+
+        final Intent intent;
+        if (uris.size() > 1) {
+            intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            intent.addCategory(Intent.CATEGORY_DEFAULT);
+            // TODO: find common mimetype
+            intent.setType("*/*");
+            intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
+        } else {
+            intent = new Intent(Intent.ACTION_SEND);
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            intent.addCategory(Intent.CATEGORY_DEFAULT);
+            intent.setData(uris.get(0));
+        }
+
+        startActivity(intent);
+    }
+
+    private void onDeleteDocuments(List<Document> docs) {
+        final Context context = getActivity();
+        final ContentResolver resolver = context.getContentResolver();
+
+        boolean hadTrouble = false;
+        for (Document doc : docs) {
+            if (!doc.isDeleteSupported()) {
+                Log.w(TAG, "Skipping " + doc);
+                hadTrouble = true;
+                continue;
+            }
+
+            try {
+                if (resolver.delete(doc.uri, null, null) != 1) {
+                    Log.w(TAG, "Failed to delete " + doc);
+                    hadTrouble = true;
+                }
+            } catch (Exception e) {
+                Log.w(TAG, "Failed to delete " + doc + ": " + e);
+                hadTrouble = true;
+            }
+        }
+
+        if (hadTrouble) {
+            Toast.makeText(context, R.string.toast_failed_delete, Toast.LENGTH_SHORT).show();
+        }
+    }
+
     private static DisplayState getDisplayState(Fragment fragment) {
         return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
     }
@@ -328,7 +434,7 @@
         public void swapDocuments(List<Document> documents) {
             mDocuments = documents;
 
-            if (documents != null && documents.isEmpty()) {
+            if (mDocuments != null && mDocuments.isEmpty()) {
                 mEmptyView.setVisibility(View.VISIBLE);
             } else {
                 mEmptyView.setVisibility(View.GONE);
@@ -342,11 +448,15 @@
             final Context context = parent.getContext();
             final DisplayState state = getDisplayState(DirectoryFragment.this);
 
+            final RootsCache roots = DocumentsApplication.getRootsCache(context);
+            final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
+                    context, mThumbSize);
+
             if (convertView == null) {
                 final LayoutInflater inflater = LayoutInflater.from(context);
-                if (state.mode == DisplayState.MODE_LIST) {
+                if (state.mode == MODE_LIST) {
                     convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
-                } else if (state.mode == DisplayState.MODE_GRID) {
+                } else if (state.mode == MODE_GRID) {
                     convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
                 } else {
                     throw new IllegalStateException();
@@ -369,7 +479,7 @@
             }
 
             if (doc.isThumbnailSupported()) {
-                final Bitmap cachedResult = ThumbnailCache.get(context).get(doc.uri);
+                final Bitmap cachedResult = thumbs.get(doc.uri);
                 if (cachedResult != null) {
                     icon.setImageBitmap(cachedResult);
                 } else {
@@ -379,7 +489,7 @@
                     task.execute(doc.uri);
                 }
             } else {
-                icon.setImageDrawable(RootsCache.resolveDocumentIcon(
+                icon.setImageDrawable(roots.resolveDocumentIcon(
                         context, doc.uri.getAuthority(), doc.mimeType));
             }
 
@@ -394,7 +504,7 @@
                     summary.setVisibility(View.INVISIBLE);
                 }
             } else if (mType == TYPE_RECENT_OPEN) {
-                final Root root = RootsCache.findRoot(context, doc);
+                final Root root = roots.findRoot(doc);
                 icon1.setVisibility(View.VISIBLE);
                 icon1.setImageDrawable(root.icon);
                 summary.setText(root.getDirectoryString());
@@ -444,11 +554,11 @@
 
     private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
         private final ImageView mTarget;
-        private final Point mSize;
+        private final Point mThumbSize;
 
-        public ThumbnailAsyncTask(ImageView target, Point size) {
+        public ThumbnailAsyncTask(ImageView target, Point thumbSize) {
             mTarget = target;
-            mSize = size;
+            mThumbSize = thumbSize;
         }
 
         @Override
@@ -464,9 +574,11 @@
             Bitmap result = null;
             try {
                 result = DocumentsContract.getThumbnail(
-                        context.getContentResolver(), uri, mSize);
+                        context.getContentResolver(), uri, mThumbSize);
                 if (result != null) {
-                    ThumbnailCache.get(context).put(uri, result);
+                    final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
+                            context, mThumbSize);
+                    thumbs.put(uri, result);
                 }
             } catch (Exception e) {
                 Log.w(TAG, "Failed to load thumbnail: " + e);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 98f9a4d..14d6fd5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -36,29 +36,27 @@
 import libcore.io.IoUtils;
 
 import java.io.FileNotFoundException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.LinkedList;
 import java.util.List;
 
-public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
+class DirectoryResult implements AutoCloseable {
+    Cursor cursor;
+    List<Document> contents = Lists.newArrayList();
+    Exception e;
+
+    @Override
+    public void close() throws Exception {
+        IoUtils.closeQuietly(cursor);
+    }
+}
+
+public class DirectoryLoader extends UriDerivativeLoader<Uri, DirectoryResult> {
 
     private final int mType;
     private Predicate<Document> mFilter;
     private Comparator<Document> mSortOrder;
 
-    /**
-     * Stub result that represents an internal error.
-     */
-    public static class ExceptionResult extends LinkedList<Document> {
-        public final Exception e;
-
-        public ExceptionResult(Exception e) {
-            this.e = e;
-        }
-    }
-
     public DirectoryLoader(Context context, Uri uri, int type, Predicate<Document> filter,
             Comparator<Document> sortOrder) {
         super(context, uri);
@@ -68,51 +66,49 @@
     }
 
     @Override
-    public List<Document> loadInBackground(Uri uri, CancellationSignal signal) {
+    public DirectoryResult loadInBackground(Uri uri, CancellationSignal signal) {
+        final DirectoryResult result = new DirectoryResult();
         try {
-            return loadInBackgroundInternal(uri, signal);
+            loadInBackgroundInternal(result, uri, signal);
         } catch (Exception e) {
-            return new ExceptionResult(e);
+            result.e = e;
         }
+        return result;
     }
 
-    private List<Document> loadInBackgroundInternal(Uri uri, CancellationSignal signal) {
-        final ArrayList<Document> result = Lists.newArrayList();
-
+    private void loadInBackgroundInternal(
+            DirectoryResult result, Uri uri, CancellationSignal signal) {
         final ContentResolver resolver = getContext().getContentResolver();
         final Cursor cursor = resolver.query(uri, null, null, null, getQuerySortOrder(), signal);
-        try {
-            while (cursor != null && cursor.moveToNext()) {
-                Document doc = null;
-                switch (mType) {
-                    case TYPE_NORMAL:
-                    case TYPE_SEARCH:
-                        doc = Document.fromDirectoryCursor(uri, cursor);
-                        break;
-                    case TYPE_RECENT_OPEN:
-                        try {
-                            doc = Document.fromRecentOpenCursor(resolver, cursor);
-                        } catch (FileNotFoundException e) {
-                            Log.w(TAG, "Failed to find recent: " + e);
-                        }
-                        break;
-                    default:
-                        throw new IllegalArgumentException("Unknown type");
-                }
+        result.cursor = cursor;
+        result.cursor.registerContentObserver(mObserver);
 
-                if (doc != null && (mFilter == null || mFilter.apply(doc))) {
-                    result.add(doc);
-                }
+        while (cursor.moveToNext()) {
+            Document doc = null;
+            switch (mType) {
+                case TYPE_NORMAL:
+                case TYPE_SEARCH:
+                    doc = Document.fromDirectoryCursor(uri, cursor);
+                    break;
+                case TYPE_RECENT_OPEN:
+                    try {
+                        doc = Document.fromRecentOpenCursor(resolver, cursor);
+                    } catch (FileNotFoundException e) {
+                        Log.w(TAG, "Failed to find recent: " + e);
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown type");
             }
-        } finally {
-            IoUtils.closeQuietly(cursor);
+
+            if (doc != null && (mFilter == null || mFilter.apply(doc))) {
+                result.contents.add(doc);
+            }
         }
 
         if (mSortOrder != null) {
-            Collections.sort(result, mSortOrder);
+            Collections.sort(result.contents, mSortOrder);
         }
-
-        return result;
     }
 
     private String getQuerySortOrder() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
new file mode 100644
index 0000000..72afd9e
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.DocumentsActivity.TAG;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.documentsui.model.Root;
+
+/**
+ * Handles {@link Root} changes which invalidate cached data.
+ */
+public class DocumentChangedReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.d(TAG, "Regenerating roots cache");
+        DocumentsApplication.getRootsCache(context).update();
+        // TODO: invalidate cached data in recents provider
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 11ccc89..091737d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,11 +16,20 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_CREATE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_GET_CONTENT;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_MANAGE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_OPEN;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_GRID;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_LIST;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_DATE;
+
 import android.app.ActionBar;
 import android.app.ActionBar.OnNavigationListener;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
+import android.content.ActivityNotFoundException;
 import android.content.ClipData;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -61,11 +70,6 @@
 public class DocumentsActivity extends Activity {
     public static final String TAG = "Documents";
 
-    public static final int ACTION_OPEN = 1;
-    public static final int ACTION_CREATE = 2;
-    public static final int ACTION_GET_CONTENT = 3;
-    public static final int ACTION_MANAGE = 4;
-
     private int mAction;
 
     private SearchView mSearchView;
@@ -76,6 +80,8 @@
 
     private final DisplayState mDisplayState = new DisplayState();
 
+    private RootsCache mRoots;
+
     /** Current user navigation stack; empty implies recents. */
     private DocumentStack mStack = new DocumentStack();
     /** Currently active search, overriding any stack. */
@@ -85,6 +91,8 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        mRoots = DocumentsApplication.getRootsCache(this);
+
         final Intent intent = getIntent();
         final String action = intent.getAction();
         if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
@@ -97,6 +105,9 @@
             mAction = ACTION_MANAGE;
         }
 
+        // TODO: unify action in single place
+        mDisplayState.action = mAction;
+
         if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
             mDisplayState.allowMultiple = intent.getBooleanExtra(
                     Intent.EXTRA_ALLOW_MULTIPLE, false);
@@ -104,6 +115,7 @@
 
         if (mAction == ACTION_MANAGE) {
             mDisplayState.acceptMimes = new String[] { "*/*" };
+            mDisplayState.allowMultiple = true;
         } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
             mDisplayState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
         } else {
@@ -131,7 +143,7 @@
         }
 
         if (mAction == ACTION_MANAGE) {
-            mDisplayState.sortOrder = DisplayState.SORT_ORDER_DATE;
+            mDisplayState.sortOrder = SORT_ORDER_DATE;
         }
 
         mRootsContainer = findViewById(R.id.container_roots);
@@ -151,7 +163,7 @@
             final String authority = rootUri.getAuthority();
             final String rootId = DocumentsContract.getRootId(rootUri);
 
-            final Root root = RootsCache.findRoot(this, authority, rootId);
+            final Root root = mRoots.findRoot(authority, rootId);
             if (root != null) {
                 onRootPicked(root, true);
             } else {
@@ -316,8 +328,8 @@
         final MenuItem list = menu.findItem(R.id.menu_list);
         final MenuItem settings = menu.findItem(R.id.menu_settings);
 
-        grid.setVisible(mDisplayState.mode != DisplayState.MODE_GRID);
-        list.setVisible(mDisplayState.mode != DisplayState.MODE_LIST);
+        grid.setVisible(mDisplayState.mode != MODE_GRID);
+        list.setVisible(mDisplayState.mode != MODE_LIST);
 
         final boolean searchVisible;
         if (mAction == ACTION_CREATE) {
@@ -360,12 +372,14 @@
         } else if (id == R.id.menu_search) {
             return false;
         } else if (id == R.id.menu_grid) {
-            mDisplayState.mode = DisplayState.MODE_GRID;
+            // TODO: persist explicit user mode for cwd
+            mDisplayState.mode = MODE_GRID;
             updateDisplayState();
             invalidateOptionsMenu();
             return true;
         } else if (id == R.id.menu_list) {
-            mDisplayState.mode = DisplayState.MODE_LIST;
+            // TODO: persist explicit user mode for cwd
+            mDisplayState.mode = MODE_LIST;
             updateDisplayState();
             invalidateOptionsMenu();
             return true;
@@ -466,9 +480,9 @@
     public Root getCurrentRoot() {
         final Document cwd = getCurrentDirectory();
         if (cwd != null) {
-            return RootsCache.findRoot(this, cwd);
+            return mRoots.findRoot(cwd);
         } else {
-            return RootsCache.getRecentsRoot(this);
+            return mRoots.getRecentsRoot();
         }
     }
 
@@ -554,6 +568,12 @@
     public void onDocumentPicked(Document doc) {
         final FragmentManager fm = getFragmentManager();
         if (doc.isDirectory()) {
+            // TODO: query display mode user preference for this dir
+            if (doc.isGridPreferred()) {
+                mDisplayState.mode = MODE_GRID;
+            } else {
+                mDisplayState.mode = MODE_LIST;
+            }
             mStack.push(doc);
             onCurrentDirectoryChanged();
         } else if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
@@ -562,16 +582,29 @@
         } else if (mAction == ACTION_CREATE) {
             // Replace selected file
             SaveFragment.get(fm).setReplaceTarget(doc);
+        } else if (mAction == ACTION_MANAGE) {
+            // Open the document
+            // TODO: trampoline activity for launching downloaded APKs
+            final Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            intent.setData(doc.uri);
+            try {
+                startActivity(intent);
+            } catch (ActivityNotFoundException ex) {
+                Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
+            }
         }
     }
 
     public void onDocumentsPicked(List<Document> docs) {
-        final int size = docs.size();
-        final Uri[] uris = new Uri[size];
-        for (int i = 0; i < size; i++) {
-            uris[i] = docs.get(i).uri;
+        if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
+            final int size = docs.size();
+            final Uri[] uris = new Uri[size];
+            for (int i = 0; i < size; i++) {
+                uris[i] = docs.get(i).uri;
+            }
+            onFinished(uris);
         }
-        onFinished(uris);
     }
 
     public void onSaveRequested(Document replaceTarget) {
@@ -645,6 +678,7 @@
     }
 
     public static class DisplayState {
+        public int action;
         public int mode = MODE_LIST;
         public String[] acceptMimes;
         public int sortOrder = SORT_ORDER_NAME;
@@ -652,6 +686,11 @@
         public boolean showSize = false;
         public boolean localOnly = false;
 
+        public static final int ACTION_OPEN = 1;
+        public static final int ACTION_CREATE = 2;
+        public static final int ACTION_GET_CONTENT = 3;
+        public static final int ACTION_MANAGE = 4;
+
         public static final int MODE_LIST = 0;
         public static final int MODE_GRID = 1;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
new file mode 100644
index 0000000..0a6cbc0
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.app.ActivityManager;
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Point;
+
+public class DocumentsApplication extends Application {
+    private RootsCache mRoots;
+    private Point mThumbnailsSize;
+    private ThumbnailCache mThumbnails;
+
+    public static RootsCache getRootsCache(Context context) {
+        return ((DocumentsApplication) context.getApplicationContext()).mRoots;
+    }
+
+    public static ThumbnailCache getThumbnailsCache(Context context, Point size) {
+        final DocumentsApplication app = (DocumentsApplication) context.getApplicationContext();
+        final ThumbnailCache thumbnails = app.mThumbnails;
+        if (!size.equals(app.mThumbnailsSize)) {
+            thumbnails.evictAll();
+            app.mThumbnailsSize = size;
+        }
+        return thumbnails;
+    }
+
+    @Override
+    public void onCreate() {
+        final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+        final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
+
+        mRoots = new RootsCache(this);
+        mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
+
+        final IntentFilter packageFilter = new IntentFilter();
+        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        packageFilter.addDataScheme("package");
+        registerReceiver(mPackageReceiver, packageFilter);
+    }
+
+    @Override
+    public void onTrimMemory(int level) {
+        super.onTrimMemory(level);
+
+        if (level >= TRIM_MEMORY_MODERATE) {
+            mThumbnails.evictAll();
+        } else if (level >= TRIM_MEMORY_BACKGROUND) {
+            mThumbnails.trimToSize(mThumbnails.size() / 2);
+        }
+    }
+
+    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // TODO: narrow changed/removed to only packages that have backends
+            mRoots.update();
+        }
+    };
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 5cdc915..5466dbf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -124,7 +124,7 @@
         }
     };
 
-    public static class RecentsCreateLoader extends UriDerivativeLoader<List<DocumentStack>> {
+    public static class RecentsCreateLoader extends UriDerivativeLoader<Uri, List<DocumentStack>> {
         public RecentsCreateLoader(Context context) {
             super(context, RecentsProvider.buildRecentCreate());
         }
@@ -169,6 +169,7 @@
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             final Context context = parent.getContext();
+            final RootsCache roots = DocumentsApplication.getRootsCache(context);
 
             if (convertView == null) {
                 final LayoutInflater inflater = LayoutInflater.from(context);
@@ -180,7 +181,7 @@
             final View summaryList = convertView.findViewById(R.id.summary_list);
 
             final DocumentStack stack = getItem(position);
-            final Root root = RootsCache.findRoot(context, stack.peek());
+            final Root root = roots.findRoot(stack.peek());
             icon.setImageDrawable(root != null ? root.icon : null);
 
             final StringBuilder builder = new StringBuilder();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index acd9396..c3b498e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -50,63 +50,67 @@
 public class RootsCache {
 
     // TODO: cache roots in local provider to avoid spinning up backends
+    // TODO: root updates should trigger UI refresh
 
-    private static boolean sCached = false;
+    private final Context mContext;
 
     /** Map from authority to cached info */
-    private static HashMap<String, DocumentsProviderInfo> sProviders = Maps.newHashMap();
+    private HashMap<String, DocumentsProviderInfo> mProviders = Maps.newHashMap();
     /** Map from (authority+rootId) to cached info */
-    private static HashMap<Pair<String, String>, Root> sRoots = Maps.newHashMap();
+    private HashMap<Pair<String, String>, Root> mRoots = Maps.newHashMap();
 
-    public static ArrayList<Root> sRootsList = Lists.newArrayList();
+    public ArrayList<Root> mRootsList = Lists.newArrayList();
 
-    private static Root sRecentsRoot;
+    private Root mRecentsRoot;
+
+    public RootsCache(Context context) {
+        mContext = context;
+        update();
+    }
 
     /**
      * Gather roots from all known storage providers.
      */
-    private static void ensureCache(Context context) {
-        if (sCached) return;
-        sCached = true;
-
-        sProviders.clear();
-        sRoots.clear();
-        sRootsList.clear();
+    @GuardedBy("ActivityThread")
+    public void update() {
+        mProviders.clear();
+        mRoots.clear();
+        mRootsList.clear();
 
         {
             // Create special root for recents
-            final Root root = Root.buildRecents(context);
-            sRootsList.add(root);
-            sRecentsRoot = root;
+            final Root root = Root.buildRecents(mContext);
+            mRootsList.add(root);
+            mRecentsRoot = root;
         }
 
         // Query for other storage backends
-        final PackageManager pm = context.getPackageManager();
+        final PackageManager pm = mContext.getPackageManager();
         final List<ProviderInfo> providers = pm.queryContentProviders(
                 null, -1, PackageManager.GET_META_DATA);
         for (ProviderInfo providerInfo : providers) {
             if (providerInfo.metaData != null && providerInfo.metaData.containsKey(
                     DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
                 final DocumentsProviderInfo info = DocumentsProviderInfo.parseInfo(
-                        context, providerInfo);
+                        mContext, providerInfo);
                 if (info == null) {
                     Log.w(TAG, "Missing info for " + providerInfo);
                     continue;
                 }
 
-                sProviders.put(info.providerInfo.authority, info);
+                mProviders.put(info.providerInfo.authority, info);
 
                 try {
                     // TODO: remove deprecated customRoots flag
                     // TODO: populate roots on background thread, and cache results
                     final Uri uri = DocumentsContract.buildRootsUri(providerInfo.authority);
-                    final Cursor cursor = context.getContentResolver()
+                    final Cursor cursor = mContext.getContentResolver()
                             .query(uri, null, null, null, null);
                     try {
                         while (cursor.moveToNext()) {
-                            final Root root = Root.fromCursor(context, info, cursor);
-                            sRoots.put(Pair.create(info.providerInfo.authority, root.rootId), root);
-                            sRootsList.add(root);
+                            final Root root = Root.fromCursor(mContext, info, cursor);
+                            mRoots.put(Pair.create(info.providerInfo.authority, root.rootId), root);
+                            mRootsList.add(root);
                         }
                     } finally {
                         cursor.close();
@@ -120,41 +124,36 @@
     }
 
     @GuardedBy("ActivityThread")
-    public static DocumentsProviderInfo findProvider(Context context, String authority) {
-        ensureCache(context);
-        return sProviders.get(authority);
+    public DocumentsProviderInfo findProvider(String authority) {
+        return mProviders.get(authority);
     }
 
     @GuardedBy("ActivityThread")
-    public static Root findRoot(Context context, String authority, String rootId) {
-        ensureCache(context);
-        return sRoots.get(Pair.create(authority, rootId));
+    public Root findRoot(String authority, String rootId) {
+        return mRoots.get(Pair.create(authority, rootId));
     }
 
     @GuardedBy("ActivityThread")
-    public static Root findRoot(Context context, Document doc) {
+    public Root findRoot(Document doc) {
         final String authority = doc.uri.getAuthority();
         final String rootId = DocumentsContract.getRootId(doc.uri);
-        return findRoot(context, authority, rootId);
+        return findRoot(authority, rootId);
     }
 
     @GuardedBy("ActivityThread")
-    public static Root getRecentsRoot(Context context) {
-        ensureCache(context);
-        return sRecentsRoot;
+    public Root getRecentsRoot() {
+        return mRecentsRoot;
     }
 
     @GuardedBy("ActivityThread")
-    public static Collection<Root> getRoots(Context context) {
-        ensureCache(context);
-        return sRootsList;
+    public Collection<Root> getRoots() {
+        return mRootsList;
     }
 
     @GuardedBy("ActivityThread")
-    public static Drawable resolveDocumentIcon(Context context, String authority, String mimeType) {
+    public Drawable resolveDocumentIcon(Context context, String authority, String mimeType) {
         // Custom icons take precedence
-        ensureCache(context);
-        final DocumentsProviderInfo info = sProviders.get(authority);
+        final DocumentsProviderInfo info = mProviders.get(authority);
         if (info != null) {
             for (Icon icon : info.customIcons) {
                 if (MimePredicate.mimeMatches(icon.mimeType, mimeType)) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 4973e1d..8a48e2a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -76,13 +76,14 @@
     public View onCreateView(
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         final Context context = inflater.getContext();
+        final RootsCache roots = DocumentsApplication.getRootsCache(context);
 
         final View view = inflater.inflate(R.layout.fragment_roots, container, false);
         mList = (ListView) view.findViewById(android.R.id.list);
         mList.setOnItemClickListener(mItemListener);
 
         final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
-        mAdapter = new SectionedRootsAdapter(context, RootsCache.getRoots(context), includeApps);
+        mAdapter = new SectionedRootsAdapter(context, roots.getRoots(), includeApps);
 
         return view;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index 69010dd..8eb81b8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -68,11 +68,12 @@
     public View onCreateView(
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         final Context context = inflater.getContext();
+        final RootsCache roots = DocumentsApplication.getRootsCache(context);
 
         final View view = inflater.inflate(R.layout.fragment_save, container, false);
 
         final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
-        icon.setImageDrawable(RootsCache.resolveDocumentIcon(
+        icon.setImageDrawable(roots.resolveDocumentIcon(
                 context, null, getArguments().getString(EXTRA_MIME_TYPE)));
 
         mDisplayName = (EditText) view.findViewById(android.R.id.title);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java b/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java
index bc7abeb..ad7cbf6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java
@@ -16,25 +16,11 @@
 
 package com.android.documentsui;
 
-import android.app.ActivityManager;
-import android.content.Context;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.util.LruCache;
 
 public class ThumbnailCache extends LruCache<Uri, Bitmap> {
-    private static ThumbnailCache sCache;
-
-    public static ThumbnailCache get(Context context) {
-        if (sCache == null) {
-            final ActivityManager am = (ActivityManager) context.getSystemService(
-                    Context.ACTIVITY_SERVICE);
-            final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
-            sCache = new ThumbnailCache(memoryClassBytes / 4);
-        }
-        return sCache;
-    }
-
     public ThumbnailCache(int maxSizeBytes) {
         super(maxSizeBytes);
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
index 1b88af4..1a5bb0c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
@@ -19,7 +19,6 @@
 import android.content.AsyncTaskLoader;
 import android.content.Context;
 import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
 
@@ -28,17 +27,16 @@
  * changes while started, manages {@link CancellationSignal}, and caches
  * returned results.
  */
-public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
-    private final ForceLoadContentObserver mObserver;
-    private boolean mObserving;
+public abstract class UriDerivativeLoader<P, R> extends AsyncTaskLoader<R> {
+    final ForceLoadContentObserver mObserver;
 
-    private final Uri mUri;
+    private final P mParam;
 
-    private T mResult;
+    private R mResult;
     private CancellationSignal mCancellationSignal;
 
     @Override
-    public final T loadInBackground() {
+    public final R loadInBackground() {
         synchronized (this) {
             if (isLoadInBackgroundCanceled()) {
                 throw new OperationCanceledException();
@@ -46,7 +44,7 @@
             mCancellationSignal = new CancellationSignal();
         }
         try {
-            return loadInBackground(mUri, mCancellationSignal);
+            return loadInBackground(mParam, mCancellationSignal);
         } finally {
             synchronized (this) {
                 mCancellationSignal = null;
@@ -54,7 +52,7 @@
         }
     }
 
-    public abstract T loadInBackground(Uri uri, CancellationSignal signal);
+    public abstract R loadInBackground(P param, CancellationSignal signal);
 
     @Override
     public void cancelLoadInBackground() {
@@ -68,12 +66,12 @@
     }
 
     @Override
-    public void deliverResult(T result) {
+    public void deliverResult(R result) {
         if (isReset()) {
             closeQuietly(result);
             return;
         }
-        T oldResult = mResult;
+        R oldResult = mResult;
         mResult = result;
 
         if (isStarted()) {
@@ -85,18 +83,14 @@
         }
     }
 
-    public UriDerivativeLoader(Context context, Uri uri) {
+    public UriDerivativeLoader(Context context, P param) {
         super(context);
         mObserver = new ForceLoadContentObserver();
-        mUri = uri;
+        mParam = param;
     }
 
     @Override
     protected void onStartLoading() {
-        if (!mObserving) {
-            getContext().getContentResolver().registerContentObserver(mUri, false, mObserver);
-            mObserving = true;
-        }
         if (mResult != null) {
             deliverResult(mResult);
         }
@@ -111,7 +105,7 @@
     }
 
     @Override
-    public void onCanceled(T result) {
+    public void onCanceled(R result) {
         closeQuietly(result);
     }
 
@@ -125,13 +119,10 @@
         closeQuietly(mResult);
         mResult = null;
 
-        if (mObserving) {
-            getContext().getContentResolver().unregisterContentObserver(mObserver);
-            mObserving = false;
-        }
+        getContext().getContentResolver().unregisterContentObserver(mObserver);
     }
 
-    private void closeQuietly(T result) {
+    private void closeQuietly(R result) {
         if (result instanceof AutoCloseable) {
             try {
                 ((AutoCloseable) result).close();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
index cf45394..c0f21cb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
@@ -143,6 +143,14 @@
         return Documents.MIME_TYPE_DIR.equals(mimeType);
     }
 
+    public boolean isGridPreferred() {
+        return (flags & Documents.FLAG_PREFERS_GRID) != 0;
+    }
+
+    public boolean isDeleteSupported() {
+        return (flags & Documents.FLAG_SUPPORTS_DELETE) != 0;
+    }
+
     private static String getCursorString(Cursor cursor, String columnName) {
         final int index = cursor.getColumnIndex(columnName);
         return (index != -1) ? cursor.getString(index) : null;
diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml
index 5272166..8bd2a6d 100644
--- a/packages/ExternalStorageProvider/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/AndroidManifest.xml
@@ -15,5 +15,18 @@
                 android:name="android.content.DOCUMENT_PROVIDER"
                 android:resource="@xml/document_provider" />
         </provider>
+
+        <!-- TODO: remove when we have real providers -->
+        <provider
+            android:name=".CloudTestDocumentsProvider"
+            android:authorities="com.android.externalstorage.cloudtest"
+            android:grantUriPermissions="true"
+            android:exported="true"
+            android:enabled="false"
+            android:permission="android.permission.MANAGE_DOCUMENTS">
+            <meta-data
+                android:name="android.content.DOCUMENT_PROVIDER"
+                android:resource="@xml/document_provider" />
+        </provider>
     </application>
 </manifest>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java
new file mode 100644
index 0000000..119d92e
--- /dev/null
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.externalstorage;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.DocumentColumns;
+import android.provider.DocumentsContract.Documents;
+import android.provider.DocumentsContract.RootColumns;
+import android.provider.DocumentsContract.Roots;
+import android.util.Log;
+
+import com.google.android.collect.Lists;
+
+import libcore.io.IoUtils;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+
+public class CloudTestDocumentsProvider extends ContentProvider {
+    private static final String TAG = "CloudTest";
+
+    private static final String AUTHORITY = "com.android.externalstorage.cloudtest";
+
+    private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+    private static final int URI_ROOTS = 1;
+    private static final int URI_ROOTS_ID = 2;
+    private static final int URI_DOCS_ID = 3;
+    private static final int URI_DOCS_ID_CONTENTS = 4;
+    private static final int URI_DOCS_ID_SEARCH = 5;
+
+    static {
+        sMatcher.addURI(AUTHORITY, "roots", URI_ROOTS);
+        sMatcher.addURI(AUTHORITY, "roots/*", URI_ROOTS_ID);
+        sMatcher.addURI(AUTHORITY, "roots/*/docs/*", URI_DOCS_ID);
+        sMatcher.addURI(AUTHORITY, "roots/*/docs/*/contents", URI_DOCS_ID_CONTENTS);
+        sMatcher.addURI(AUTHORITY, "roots/*/docs/*/search", URI_DOCS_ID_SEARCH);
+    }
+
+    private static final String[] ALL_ROOTS_COLUMNS = new String[] {
+            RootColumns.ROOT_ID, RootColumns.ROOT_TYPE, RootColumns.ICON, RootColumns.TITLE,
+            RootColumns.SUMMARY, RootColumns.AVAILABLE_BYTES
+    };
+
+    private static final String[] ALL_DOCUMENTS_COLUMNS = new String[] {
+            DocumentColumns.DOC_ID, DocumentColumns.DISPLAY_NAME, DocumentColumns.SIZE,
+            DocumentColumns.MIME_TYPE, DocumentColumns.LAST_MODIFIED, DocumentColumns.FLAGS
+    };
+
+    private List<String> mKnownDocs = Lists.newArrayList("meow.png", "kittens.pdf");
+
+    private int mPage;
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        switch (sMatcher.match(uri)) {
+            case URI_ROOTS: {
+                final MatrixCursor result = new MatrixCursor(
+                        projection != null ? projection : ALL_ROOTS_COLUMNS);
+                includeDefaultRoot(result);
+                return result;
+            }
+            case URI_ROOTS_ID: {
+                final MatrixCursor result = new MatrixCursor(
+                        projection != null ? projection : ALL_ROOTS_COLUMNS);
+                includeDefaultRoot(result);
+                return result;
+            }
+            case URI_DOCS_ID: {
+                final String docId = DocumentsContract.getDocId(uri);
+                final MatrixCursor result = new MatrixCursor(
+                        projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
+                includeDoc(result, docId);
+                return result;
+            }
+            case URI_DOCS_ID_CONTENTS: {
+                final CloudCursor result = new CloudCursor(
+                        projection != null ? projection : ALL_DOCUMENTS_COLUMNS, uri);
+                for (String docId : mKnownDocs) {
+                    includeDoc(result, docId);
+                }
+                if (mPage < 3) {
+                    result.setHasMore();
+                }
+                result.setNotificationUri(getContext().getContentResolver(), uri);
+                return result;
+            }
+            default: {
+                throw new UnsupportedOperationException("Unsupported Uri " + uri);
+            }
+        }
+    }
+
+    private void includeDefaultRoot(MatrixCursor result) {
+        final RowBuilder row = result.newRow();
+        row.offer(RootColumns.ROOT_ID, "testroot");
+        row.offer(RootColumns.ROOT_TYPE, Roots.ROOT_TYPE_SERVICE);
+        row.offer(RootColumns.TITLE, "_TestTitle");
+        row.offer(RootColumns.SUMMARY, "_TestSummary");
+    }
+
+    private void includeDoc(MatrixCursor result, String docId) {
+        int flags = 0;
+
+        final String mimeType;
+        if (Documents.DOC_ID_ROOT.equals(docId)) {
+            mimeType = Documents.MIME_TYPE_DIR;
+        } else {
+            mimeType = "application/octet-stream";
+        }
+
+        final RowBuilder row = result.newRow();
+        row.offer(DocumentColumns.DOC_ID, docId);
+        row.offer(DocumentColumns.DISPLAY_NAME, docId);
+        row.offer(DocumentColumns.MIME_TYPE, mimeType);
+        row.offer(DocumentColumns.LAST_MODIFIED, System.currentTimeMillis());
+        row.offer(DocumentColumns.FLAGS, flags);
+    }
+
+    private class CloudCursor extends MatrixCursor {
+        private final Uri mUri;
+        private Bundle mExtras = new Bundle();
+
+        public CloudCursor(String[] columnNames, Uri uri) {
+            super(columnNames);
+            mUri = uri;
+        }
+
+        public void setHasMore() {
+            mExtras.putBoolean(DocumentsContract.EXTRA_HAS_MORE, true);
+        }
+
+        @Override
+        public Bundle getExtras() {
+            Log.d(TAG, "getExtras() " + mExtras);
+            return mExtras;
+        }
+
+        @Override
+        public Bundle respond(Bundle extras) {
+            extras.size();
+            Log.d(TAG, "respond() " + extras);
+            if (extras.getBoolean(DocumentsContract.EXTRA_REQUEST_MORE, false)) {
+                new CloudTask().execute(mUri);
+            }
+            return Bundle.EMPTY;
+        }
+    }
+
+    private class CloudTask extends AsyncTask<Uri, Void, Void> {
+        @Override
+        protected Void doInBackground(Uri... uris) {
+            final Uri uri = uris[0];
+
+            SystemClock.sleep(1000);
+
+            // Grab some files from the cloud
+            for (int i = 0; i < 5; i++) {
+                mKnownDocs.add("cloud-page" + mPage + "-file" + i);
+            }
+            mPage++;
+
+            Log.d(TAG, "Loaded more; notifying " + uri);
+            getContext().getContentResolver().notifyChange(uri, null, false);
+            return null;
+        }
+    }
+
+    private interface TypeQuery {
+        final String[] PROJECTION = {
+                DocumentColumns.MIME_TYPE };
+
+        final int MIME_TYPE = 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        switch (sMatcher.match(uri)) {
+            case URI_ROOTS: {
+                return Roots.MIME_TYPE_DIR;
+            }
+            case URI_ROOTS_ID: {
+                return Roots.MIME_TYPE_ITEM;
+            }
+            case URI_DOCS_ID: {
+                final Cursor cursor = query(uri, TypeQuery.PROJECTION, null, null, null);
+                try {
+                    if (cursor.moveToFirst()) {
+                        return cursor.getString(TypeQuery.MIME_TYPE);
+                    } else {
+                        return null;
+                    }
+                } finally {
+                    IoUtils.closeQuietly(cursor);
+                }
+            }
+            default: {
+                throw new UnsupportedOperationException("Unsupported Uri " + uri);
+            }
+        }
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        throw new UnsupportedOperationException("Unsupported Uri " + uri);
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException("Unsupported Uri " + uri);
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("Unsupported Uri " + uri);
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("Unsupported Uri " + uri);
+    }
+}
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 7d77c48..f3106da 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -38,6 +38,9 @@
     <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
 
+    <!-- Permission for the Hotword detector service -->
+    <uses-permission android:name="com.google.android.googlequicksearchbox.SEARCH_API" />
+
     <application android:label="@string/app_name"
         android:process="com.android.systemui"
         android:persistent="true" >
diff --git a/packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java b/packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java
new file mode 100644
index 0000000..94733d4
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.google.android.search.service.IHotwordService;
+import com.google.android.search.service.IHotwordServiceCallback;
+
+/**
+ * Utility class with its callbacks to simplify usage of {@link IHotwordService}.
+ *
+ * The client is meant to be used for a single hotword detection in a session.
+ * start() -> stop(); client is asked to stop & disconnect from the service.
+ * start() -> onHotwordDetected(); client disconnects from the service automatically.
+ */
+public class HotwordServiceClient implements Handler.Callback {
+    private static final String TAG = "HotwordServiceClient";
+    private static final boolean DBG = true;
+    private static final String ACTION_HOTWORD =
+            "com.google.android.search.service.IHotwordService";
+
+    private static final int MSG_SERVICE_CONNECTED = 0;
+    private static final int MSG_SERVICE_DISCONNECTED = 1;
+    private static final int MSG_HOTWORD_STARTED = 2;
+    private static final int MSG_HOTWORD_STOPPED = 3;
+    private static final int MSG_HOTWORD_DETECTED = 4;
+
+    private final Context mContext;
+    private final Callback mClientCallback;
+    private final Handler mHandler;
+
+    private IHotwordService mService;
+
+    public HotwordServiceClient(Context context, Callback callback) {
+        mContext = context;
+        mClientCallback = callback;
+        mHandler = new Handler(this);
+    }
+
+    public interface Callback {
+        void onServiceConnected();
+        void onServiceDisconnected();
+        void onHotwordDetectionStarted();
+        void onHotwordDetectionStopped();
+        void onHotwordDetected(String action);
+    }
+
+    /**
+     * Binds to the {@link IHotwordService} and starts hotword detection
+     * when the service is connected.
+     *
+     * @return false if the service can't be bound to.
+     */
+    public synchronized boolean start() {
+        if (mService != null) {
+            if (DBG) Log.d(TAG, "Multiple call to start(), service was already bound");
+            return true;
+        } else {
+            // TODO: The hotword service is currently hosted within the search app
+            // so the component handling the assist intent should handle hotwording
+            // as well.
+            final Intent intent =
+                    ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                            .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+            if (intent == null) {
+                return false;
+            }
+
+            Intent hotwordIntent = new Intent(ACTION_HOTWORD);
+            hotwordIntent.fillIn(intent, Intent.FILL_IN_PACKAGE);
+            return mContext.bindService(
+                    hotwordIntent,
+                   mConnection,
+                   Context.BIND_AUTO_CREATE);
+        }
+    }
+
+    /**
+     * Unbinds from the the {@link IHotwordService}.
+     */
+    public synchronized void stop() {
+        if (mService != null) {
+            mContext.unbindService(mConnection);
+            mService = null;
+        }
+    }
+
+    @Override
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_SERVICE_CONNECTED:
+                handleServiceConnected();
+                break;
+            case MSG_SERVICE_DISCONNECTED:
+                handleServiceDisconnected();
+                break;
+            case MSG_HOTWORD_STARTED:
+                handleHotwordDetectionStarted();
+                break;
+            case MSG_HOTWORD_STOPPED:
+                handleHotwordDetectionStopped();
+                break;
+            case MSG_HOTWORD_DETECTED:
+                handleHotwordDetected((String) msg.obj);
+                break;
+            default:
+                if (DBG) Log.e(TAG, "Unhandled message");
+                return false;
+        }
+        return true;
+    }
+
+    private void handleServiceConnected() {
+        if (DBG) Log.d(TAG, "handleServiceConnected()");
+        if (mClientCallback != null) mClientCallback.onServiceConnected();
+        try {
+            mService.requestHotwordDetection(mServiceCallback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception while registering callback", e);
+            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
+        }
+    }
+
+    private void handleServiceDisconnected() {
+        if (DBG) Log.d(TAG, "handleServiceDisconnected()");
+        mService = null;
+        if (mClientCallback != null) mClientCallback.onServiceDisconnected();
+    }
+
+    private void handleHotwordDetectionStarted() {
+        if (DBG) Log.d(TAG, "handleHotwordDetectionStarted()");
+        if (mClientCallback != null) mClientCallback.onHotwordDetectionStarted();
+    }
+
+    private void handleHotwordDetectionStopped() {
+        if (DBG) Log.d(TAG, "handleHotwordDetectionStopped()");
+        if (mClientCallback != null) mClientCallback.onHotwordDetectionStopped();
+    }
+
+    void handleHotwordDetected(final String action) {
+        if (DBG) Log.d(TAG, "handleHotwordDetected()");
+        if (mClientCallback != null) mClientCallback.onHotwordDetected(action);
+        stop();
+    }
+
+    /**
+     * Implements service connection methods.
+     */
+    private ServiceConnection mConnection = new ServiceConnection() {
+        /**
+         * Called when the service connects after calling bind().
+         */
+        public void onServiceConnected(ComponentName className, IBinder iservice) {
+            mService = IHotwordService.Stub.asInterface(iservice);
+            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
+        }
+
+        /**
+         * Called if the service unexpectedly disconnects. This indicates an error.
+         */
+        public void onServiceDisconnected(ComponentName className) {
+            mService = null;
+            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
+        }
+    };
+
+    /**
+     * Implements the AIDL IHotwordServiceCallback interface.
+     */
+    private final IHotwordServiceCallback mServiceCallback = new IHotwordServiceCallback.Stub() {
+
+        public void onHotwordDetectionStarted() {
+            mHandler.sendEmptyMessage(MSG_HOTWORD_STARTED);
+        }
+
+        public void onHotwordDetectionStopped() {
+            mHandler.sendEmptyMessage(MSG_HOTWORD_STOPPED);
+        }
+
+        public void onHotwordDetected(String action) {
+            mHandler.obtainMessage(MSG_HOTWORD_DETECTED, action).sendToTarget();
+        }
+    };
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index 4d891be..1c658e3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -22,8 +22,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
@@ -34,12 +37,15 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.multiwaveview.GlowPadView;
 import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
 
 public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
     private static final boolean DEBUG = KeyguardHostView.DEBUG;
     private static final String TAG = "SecuritySelectorView";
     private static final String ASSIST_ICON_METADATA_NAME =
         "com.android.systemui.action_assist_icon";
+    // Flag to enable/disable hotword detection on lock screen.
+    private static final boolean FLAG_HOTWORD = true;
 
     private KeyguardSecurityCallback mCallback;
     private GlowPadView mGlowPadView;
@@ -51,11 +57,15 @@
     private LockPatternUtils mLockPatternUtils;
     private SecurityMessageDisplay mSecurityMessageDisplay;
     private Drawable mBouncerFrame;
+    private HotwordServiceClient mHotwordClient;
 
     OnTriggerListener mOnTriggerListener = new OnTriggerListener() {
 
         public void onTrigger(View v, int target) {
             final int resId = mGlowPadView.getResourceIdForTarget(target);
+            if (FLAG_HOTWORD) {
+                maybeStopHotwordDetector();
+            }
             switch (resId) {
                 case R.drawable.ic_action_assist_generic:
                     Intent assistIntent =
@@ -103,7 +113,7 @@
 
     };
 
-    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
         public void onDevicePolicyManagerStateChanged() {
@@ -114,6 +124,24 @@
         public void onSimStateChanged(State simState) {
             updateTargets();
         }
+
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
+            if (FLAG_HOTWORD) {
+                // We need to stop the hotwording when a phone call comes in
+                // TODO(sansid): This is not really needed if onPause triggers
+                // when we navigate away from the keyguard
+                if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
+                    if (DEBUG) Log.d(TAG, "Stopping due to CALL_STATE_RINGING");
+                    maybeStopHotwordDetector();
+                }
+            }
+        }
+
+        @Override
+        public void onUserSwitching(int userId) {
+            maybeStopHotwordDetector();
+        }
     };
 
     private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
@@ -152,6 +180,9 @@
         mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
         View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
         mBouncerFrame = bouncerFrameView.getBackground();
+        if (FLAG_HOTWORD) {
+            mHotwordClient = new HotwordServiceClient(getContext(), mHotwordCallback);
+        }
     }
 
     public void setCarrierArea(View carrierArea) {
@@ -254,12 +285,22 @@
 
     @Override
     public void onPause() {
-        KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mInfoCallback);
+        KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mUpdateCallback);
     }
 
     @Override
     public void onResume(int reason) {
-        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
+        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mUpdateCallback);
+        // TODO: Figure out if there's a better way to do it.
+        // Right now we don't get onPause at all, and onResume gets called
+        // multiple times (even when the screen is turned off with VIEW_REVEALED)
+        if (reason == SCREEN_ON) {
+            if (!KeyguardUpdateMonitor.getInstance(getContext()).isSwitchingUser()) {
+                maybeStartHotwordDetector();
+            }
+        } else {
+            maybeStopHotwordDetector();
+        }
     }
 
     @Override
@@ -280,4 +321,83 @@
         KeyguardSecurityViewHelper.
                 hideBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
     }
+
+    /**
+     * Start the hotword detector if:
+     * <li> HOTWORDING_ENABLED is true and
+     * <li> HotwordUnlock is initialized and
+     * <li> TelephonyManager is in CALL_STATE_IDLE
+     *
+     * If this method is called when the screen is off,
+     * it attempts to stop hotwording if it's running.
+     */
+    private void maybeStartHotwordDetector() {
+        if (FLAG_HOTWORD) {
+            if (DEBUG) Log.d(TAG, "maybeStartHotwordDetector()");
+            // Don't start it if the screen is off or not showing
+            PowerManager powerManager = (PowerManager) getContext().getSystemService(
+                    Context.POWER_SERVICE);
+            if (!powerManager.isScreenOn()) {
+                if (DEBUG) Log.d(TAG, "screen was off, not starting");
+                return;
+            }
+
+            KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
+            if (monitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE) {
+                if (DEBUG) Log.d(TAG, "Call underway, not starting");
+                return;
+            }
+            if (!mHotwordClient.start()) {
+                Log.w(TAG, "Failed to start the hotword detector");
+            }
+        }
+    }
+
+    /**
+     * Stop hotword detector if HOTWORDING_ENABLED is true.
+     */
+    private void maybeStopHotwordDetector() {
+        if (FLAG_HOTWORD) {
+            if (DEBUG) Log.d(TAG, "maybeStopHotwordDetector()");
+            mHotwordClient.stop();
+        }
+    }
+
+    private final HotwordServiceClient.Callback mHotwordCallback =
+            new HotwordServiceClient.Callback() {
+        private static final String TAG = "HotwordServiceClient.Callback";
+
+        @Override
+        public void onServiceConnected() {
+            if (DEBUG) Log.d(TAG, "onServiceConnected()");
+        }
+
+        @Override
+        public void onServiceDisconnected() {
+            if (DEBUG) Log.d(TAG, "onServiceDisconnected()");
+        }
+
+        @Override
+        public void onHotwordDetectionStarted() {
+            if (DEBUG) Log.d(TAG, "onHotwordDetectionStarted()");
+            // TODO: Change the usage of SecurityMessageDisplay to a better visual indication.
+            mSecurityMessageDisplay.setMessage("\"Ok Google...\"", true);
+        }
+
+        @Override
+        public void onHotwordDetectionStopped() {
+            if (DEBUG) Log.d(TAG, "onHotwordDetectionStopped()");
+            // TODO: Change the usage of SecurityMessageDisplay to a better visual indication.
+        }
+
+        @Override
+        public void onHotwordDetected(String action) {
+            if (DEBUG) Log.d(TAG, "onHotwordDetected(" + action + ")");
+            if (action != null) {
+                Intent intent = new Intent(action);
+                mActivityLauncher.launchActivity(intent, true, true, null, null);
+            }
+            mCallback.userActivity(0);
+        }
+    };
 }
diff --git a/packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl b/packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl
new file mode 100644
index 0000000..e053d7d
--- /dev/null
+++ b/packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.search.service;
+
+import com.google.android.search.service.IHotwordServiceCallback;
+
+/**
+ * Interface exposing hotword detector as a service.
+ */
+oneway interface IHotwordService {
+
+    /**
+     * Indicates a desire to start hotword detection.
+     * It's best-effort and the client should rely on
+     * the callbacks to figure out if hotwording was actually
+     * started or not.
+     *
+     * @param a callback to notify of hotword events.
+     */
+    void requestHotwordDetection(in IHotwordServiceCallback callback);
+}
diff --git a/packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl b/packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl
new file mode 100644
index 0000000..7b3765f
--- /dev/null
+++ b/packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.search.service;
+
+/**
+ * Interface implemented by users of Hotword service to get callbacks
+ * for hotword events.
+ */
+oneway interface IHotwordServiceCallback {
+
+    /** Hotword detection start/stop callbacks */
+    void onHotwordDetectionStarted();
+    void onHotwordDetectionStopped();
+
+    /**
+     * Called back when hotword is detected.
+     * The action tells the client what action to take, post hotword-detection.
+     */
+    void onHotwordDetected(in String action);
+}
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index c00639d..1f10af8 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -18,7 +18,7 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.printspooler"
-        android:sharedUserId="android.uid.printspooler"
+        android:sharedUserId="android.uid.system"
         android:versionName="1"
         android:versionCode="1"
         coreApp="true">
@@ -51,9 +51,10 @@
         </activity>
 
         <activity
-            android:name=".ChoosePrinterActivity"
-            android:exported="false"
-            android:theme="@android:style/Theme.Holo.Light">
+            android:name=".SelectPrinterActivity"
+            android:label="@string/all_printers_label"
+            android:theme="@style/SelectPrinterActivityTheme"
+            android:exported="false">
         </activity>
 
         <receiver
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.png b/packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.png
new file mode 100644
index 0000000..4b68f52
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.png b/packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.png
new file mode 100644
index 0000000..15ffadd
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.png
new file mode 100644
index 0000000..420510e
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.png
Binary files differ
diff --git a/packages/PrintSpooler/res/layout/choose_printer_activity.xml b/packages/PrintSpooler/res/layout/choose_printer_activity.xml
deleted file mode 100644
index c34a108..0000000
--- a/packages/PrintSpooler/res/layout/choose_printer_activity.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<ListView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/list_view"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="vertical">
-</ListView>
-
diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
index a0c111b..7817094 100644
--- a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
+++ b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
@@ -20,9 +20,4 @@
     android:layout_height="wrap_content"
     android:layout_gravity="center"
     android:background="@color/container_background">
-
-    <include
-        layout="@layout/print_job_config_activity_content_editing">
-    </include>
-
 </FrameLayout>
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
new file mode 100644
index 0000000..f4e1853
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <fragment
+        android:name="com.android.printspooler.SelectPrinterFragment"
+        android:id="@+id/select_printer_fragment"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+    </fragment>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
index 002cc14..d14c064 100644
--- a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
@@ -15,7 +15,7 @@
 -->
 
 <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
+    android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:paddingStart="8dip"
     android:paddingEnd="8dip"
diff --git a/packages/PrintSpooler/res/menu/choose_printer_activity.xml b/packages/PrintSpooler/res/menu/choose_printer_activity.xml
deleted file mode 100644
index 3774279..0000000
--- a/packages/PrintSpooler/res/menu/choose_printer_activity.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <item
-        android:id="@+id/action_search"
-        android:title="@string/search"
-        android:icon="@*android:drawable/ic_menu_search_holo_light"
-        android:actionViewClass="android.widget.SearchView"
-        android:showAsAction="ifRoom"
-        android:alphabeticShortcut="f"
-         android:imeOptions="actionSearch">
-    </item>
-
-</menu>
diff --git a/packages/PrintSpooler/res/menu/select_printer_activity.xml b/packages/PrintSpooler/res/menu/select_printer_activity.xml
new file mode 100644
index 0000000..28fbd35
--- /dev/null
+++ b/packages/PrintSpooler/res/menu/select_printer_activity.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_search"
+        android:title="@string/search"
+        android:icon="@*android:drawable/ic_menu_search_holo_light"
+        android:actionViewClass="android.widget.SearchView"
+        android:showAsAction="ifRoom"
+        android:alphabeticShortcut="f"
+        android:imeOptions="actionSearch">
+    </item>
+
+    <item
+        android:id="@+id/action_add_printer"
+        android:title="@null"
+        android:icon="@drawable/ic_menu_add"
+        android:showAsAction="ifRoom"
+        android:alphabeticShortcut="a">
+    </item>
+
+</menu>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 1cd611f..41fc516 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -58,11 +58,32 @@
     <!-- Title for the temporary dialog show while an app is generating a print job. [CHAR LIMIT=30] -->
     <string name="generating_print_job">Generating print job</string>
 
-    <!-- Choose printer activity -->
+    <!-- Title for the save as PDF option in the printer list. [CHAR LIMIT=30] -->
+    <string name="save_as_pdf">Save as PDF</string>
+
+    <!-- Title for the open all printers UI option in the printer list. [CHAR LIMIT=30] -->
+    <string name="all_printers">All printers\.\.\.</string>
+
+    <!-- Title for the searching for printers option in the printer list
+         (only option if not printers are available). [CHAR LIMIT=40] -->
+    <string name="searching_for_printers">Searching for printers\.\.\.</string>
+
+    <!-- Select printer activity -->
 
     <!-- Title for the share action bar menu item. [CHAR LIMIT=20] -->
     <string name="search">Search</string>
 
+    <!-- Title for the select printer activity. [CHAR LIMIT=30] -->
+    <string name="all_printers_label">All printers</string>
+
+    <!-- Add printer dialog  -->
+
+    <!-- Title for the alert dialog for selecting a print service. [CHAR LIMIT=50] -->
+    <string name="choose_print_service">Choose print service</string>
+
+    <!-- Title for the button to search the play store for print services. [CHAR LIMIT=50] -->
+    <string name="search_play_store">Search in play store</string>
+
     <!-- Notifications -->
 
     <!-- Template for the notificaiton label for a printing print job. [CHAR LIMIT=25] -->
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index ab16c65..831b0ec 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -24,4 +24,12 @@
         <item name="android:colorBackgroundCacheHint">@android:color/transparent</item>
     </style>
 
+    <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.Holo.Light">
+        <item name="android:actionBarStyle">@style/SelectPrinterActivityActionBarStyle</item>
+    </style>
+
+    <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.Holo.ActionBar">
+        <item name="android:displayOptions">showTitle</item>
+    </style>
+
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/AvailablePrinterProvider.java b/packages/PrintSpooler/src/com/android/printspooler/AvailablePrinterProvider.java
deleted file mode 100644
index 658a224..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/AvailablePrinterProvider.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.print.IPrinterDiscoverySessionController;
-import android.print.IPrinterDiscoverySessionObserver;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
-import android.util.ArraySet;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-/**
- * This class is responsible to provide the available printers.
- * It starts and stops printer discovery and manages the returned
- * printers.
- */
-public class AvailablePrinterProvider extends DataProvider<PrinterInfo>
-        implements DataLoader {
-    private static final String LOG_TAG = "AvailablePrinterProvider";
-
-    private final Set<PrinterId> mPrinteIdsSet = new ArraySet<PrinterId>();
-
-    private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
-
-    private final List<PrinterId> mPriorityList;
-
-    private PrinterDiscoverySession mDiscoverySession;
-
-    public AvailablePrinterProvider(Context context, List<PrinterId> priorityList) {
-        mDiscoverySession = new PrinterDiscoverySession(context.getMainLooper());
-        mPriorityList = priorityList;
-    }
-
-    @Override
-    public void startLoadData() {
-        mDiscoverySession.open();
-    }
-
-    @Override
-    public void stopLoadData() {
-        mDiscoverySession.close();
-    }
-
-    @Override
-    public int getItemCount() {
-        return mPrinters.size();
-    }
-
-    @Override
-    public int getItemIndex(PrinterInfo printer) {
-        return mPrinters.indexOf(printer);
-    }
-
-    @Override
-    public PrinterInfo getItemAt(int index) {
-        return mPrinters.get(index);
-    }
-
-    public void refreshItem(int index) {
-        PrinterInfo printer = getItemAt(index);
-        mDiscoverySession.requestPrinterUpdate(printer.getId());
-    }
-
-    private void addPrinters(List<PrinterInfo> printers) {
-        boolean addedPrinters = false;
-
-        final int addedPrinterCount = printers.size();
-        for (int i = 0; i < addedPrinterCount; i++) {
-           PrinterInfo addedPrinter = printers.get(i);
-           if (mPrinteIdsSet.add(addedPrinter.getId())) {
-               mPrinters.add(addedPrinter);
-               addedPrinters = true;
-           }
-        }
-
-        if (addedPrinters) {
-            notifyChanged();
-        }
-    }
-
-    private void updatePrinters(List<PrinterInfo> printers) {
-        boolean updatedPrinters = false;
-
-        final int updatedPrinterCount = printers.size();
-        for (int i = 0; i < updatedPrinterCount; i++) {
-            PrinterInfo updatedPrinter = printers.get(i);
-            if (mPrinteIdsSet.contains(updatedPrinter.getId())) {
-                final int oldPrinterCount = mPrinters.size();
-                for (int j = 0; j < oldPrinterCount; j++) {
-                    PrinterInfo oldPrinter = mPrinters.get(j);
-                    if (updatedPrinter.getId().equals(oldPrinter.getId())) {
-                        mPrinters.set(j, updatedPrinter);
-                        updatedPrinters = true;
-                        break;
-                    }
-                }
-            }
-        }
-
-        if (updatedPrinters) {
-            notifyChanged();
-        }
-    }
-
-    private void removePrinters(List<PrinterId> printers) {
-        boolean removedPrinters = false;
-
-        final int removedPrinterCount = printers.size();
-        for (int i = 0; i < removedPrinterCount; i++) {
-            PrinterId removedPrinter = printers.get(i);
-            if (mPrinteIdsSet.contains(removedPrinter)) {
-                mPrinteIdsSet.remove(removedPrinter);
-                Iterator<PrinterInfo> iterator = mPrinters.iterator();
-                while (iterator.hasNext()) {
-                    PrinterInfo oldPrinter = iterator.next();
-                    if (removedPrinter.equals(oldPrinter.getId())) {
-                        iterator.remove();
-                        break;
-                    }
-                }
-            }
-        }
-
-        if (removedPrinters) {
-            notifyChanged();
-        }
-    }
-
-    private final class PrinterDiscoverySession {
-
-        private final Handler mHandler;
-
-        private final IPrinterDiscoverySessionObserver mObserver;
-
-        private IPrinterDiscoverySessionController mController;
-
-        public PrinterDiscoverySession(Looper looper) {
-            mHandler = new SessionHandler(looper);
-            mObserver = new PrinterDiscoverySessionObserver(this);
-        }
-
-        public void open() {
-            PrintSpooler.peekInstance().createPrinterDiscoverySession(
-                    mObserver);
-        }
-
-        public void close() {
-            if (mController != null) {
-                try {
-                    mController.close();
-                } catch (RemoteException re) {
-                    Log.e(LOG_TAG, "Error closing printer discovery session", re);
-                } finally {
-                    mController = null;
-                }
-            }
-        }
-
-        public void requestPrinterUpdate(PrinterId printerId) {
-            if (mController != null) {
-                try {
-                    mController.requestPrinterUpdate(printerId);
-                } catch (RemoteException re) {
-                    Log.e(LOG_TAG, "Error requesting printer udpdate", re);
-                }
-            }
-        }
-
-        private final class SessionHandler extends Handler {
-            public static final int MSG_SET_CONTROLLER = 1;
-            public static final int MSG_ON_PRINTERS_ADDED = 2;
-            public static final int MSG_ON_PRINTERS_REMOVED = 3;
-            public static final int MSG_ON_PRINTERS_UPDATED = 4;
-
-            public SessionHandler(Looper looper) {
-                super(looper, null, false);
-            }
-
-            @Override
-            @SuppressWarnings("unchecked")
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_SET_CONTROLLER: {
-                        mController = (IPrinterDiscoverySessionController) message.obj;
-                        try {
-                            mController.open(mPriorityList);
-                        } catch (RemoteException e) {
-                            Log.e(LOG_TAG, "Error starting printer discovery");
-                        }
-                    } break;
-
-                    case MSG_ON_PRINTERS_ADDED: {
-                        List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
-                        addPrinters(printers);
-                    } break;
-
-                    case MSG_ON_PRINTERS_REMOVED: {
-                        List<PrinterId> printers = (List<PrinterId>) message.obj;
-                        removePrinters(printers);
-                    } break;
-
-                    case MSG_ON_PRINTERS_UPDATED: {
-                        List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
-                        updatePrinters(printers);
-                    } break;
-                };
-            }
-        }
-    }
-
-    private static final class PrinterDiscoverySessionObserver
-            extends IPrinterDiscoverySessionObserver.Stub {
-
-        private final WeakReference<PrinterDiscoverySession> mWeakSession;
-
-        public PrinterDiscoverySessionObserver(PrinterDiscoverySession session) {
-            mWeakSession = new WeakReference<PrinterDiscoverySession>(session);
-        }
-
-        @Override
-        public void setController(IPrinterDiscoverySessionController controller) {
-            PrinterDiscoverySession sesison = mWeakSession.get();
-            if (sesison != null) {
-                sesison.mHandler.obtainMessage(
-                        PrinterDiscoverySession.SessionHandler.MSG_SET_CONTROLLER,
-                        controller).sendToTarget();
-            }
-        }
-
-        @Override
-        public void onPrintersAdded(List<PrinterInfo> printers) {
-            PrinterDiscoverySession sesison = mWeakSession.get();
-            if (sesison != null) {
-                sesison.mHandler.obtainMessage(
-                        PrinterDiscoverySession.SessionHandler.MSG_ON_PRINTERS_ADDED,
-                        printers).sendToTarget();
-            }
-        }
-
-        @Override
-        public void onPrintersRemoved(List<PrinterId> printers) {
-            PrinterDiscoverySession session = mWeakSession.get();
-            if (session != null) {
-                session.mHandler.obtainMessage(
-                        PrinterDiscoverySession.SessionHandler.MSG_ON_PRINTERS_REMOVED,
-                        printers).sendToTarget();
-            }
-        }
-
-        @Override
-        public void onPrintersUpdated(List<PrinterInfo> printers) {
-            PrinterDiscoverySession session = mWeakSession.get();
-            if (session != null) {
-                session.mHandler.obtainMessage(
-                        PrinterDiscoverySession.SessionHandler.MSG_ON_PRINTERS_UPDATED,
-                        printers).sendToTarget();
-            }
-        }
-    };
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ChoosePrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ChoosePrinterActivity.java
deleted file mode 100644
index 8b0dd66a..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/ChoosePrinterActivity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class ChoosePrinterActivity extends Activity {
-
-    @Override
-    public void onCreate(Bundle bundle) {
-        setContentView(R.layout.choose_printer_activity);
-    }
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/DataLoader.java b/packages/PrintSpooler/src/com/android/printspooler/DataLoader.java
deleted file mode 100644
index 82cc2e1..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/DataLoader.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-/**
- * This is the contract for a class that know how to load data.
- */
-public interface DataLoader {
-
-    /**
-     * Requests to start loading data.
-     */
-    public void startLoadData();
-
-    /**
-     * Requests to stop loading data.
-     */
-    public void stopLoadData();
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/DataProvider.java b/packages/PrintSpooler/src/com/android/printspooler/DataProvider.java
deleted file mode 100644
index 7b10903..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/DataProvider.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-import android.database.DataSetObservable;
-
-/**
- * This is the simple contract for data providers.
- *
- * @param <T> The type of the providers data.
- */
-public abstract class DataProvider<T> extends DataSetObservable {
-
-    /**
-     * Gets the number of items.
-     *
-     * @return The item count.
-     */
-    public abstract int getItemCount();
-
-    /**
-     * Gets the index of an item.
-     *
-     * @param item The item.
-     * @return The item index.
-     */
-    public abstract int getItemIndex(T item);
-
-    /**
-     * Gets an item at a given position.
-     *
-     * @param index The position.
-     * @return The item.
-     */
-    public abstract T getItemAt(int index);
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FavoritePrinterProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FavoritePrinterProvider.java
deleted file mode 100644
index 2c539d1..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/FavoritePrinterProvider.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
-import android.util.ArrayMap;
-import android.util.AtomicFile;
-import android.util.Log;
-import android.util.Slog;
-import android.util.Xml;
-
-import com.android.internal.util.FastXmlSerializer;
-
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class provides the favorite printers based on past usage.
- */
-final class FavoritePrinterProvider extends DataProvider<PrinterInfo> implements DataLoader {
-
-    private static final String LOG_TAG = "FavoritePrinterProvider";
-
-    private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
-
-    private static final int MAX_HISTORY_LENGTH = 50;
-
-    private static final double WEIGHT_DECAY_COEFFICIENT = 0.95f;
-
-    private final List<PrinterRecord> mHistoricalPrinters = new ArrayList<PrinterRecord>();
-
-    private final List<PrinterRecord> mFavoritePrinters = new ArrayList<PrinterRecord>();
-
-    private final PersistenceManager mPersistenceManager;
-
-    public FavoritePrinterProvider(Context context) {
-        mPersistenceManager = new PersistenceManager(context);
-    }
-
-    public void addPrinter(PrinterInfo printer) {
-        addPrinterInternal(printer);
-        computeFavoritePrinters();
-        mPersistenceManager.writeState();
-    }
-
-    @Override
-    public int getItemCount() {
-        return mFavoritePrinters.size();
-    }
-
-    @Override
-    public PrinterInfo getItemAt(int index) {
-        return mFavoritePrinters.get(index).printer;
-    }
-
-    @Override
-    public int getItemIndex(PrinterInfo printer) {
-        return mFavoritePrinters.indexOf(printer);
-    }
-
-    @Override
-    public void startLoadData() {
-        mPersistenceManager.readStateLocked();
-        computeFavoritePrinters();
-    }
-
-    @Override
-    public void stopLoadData() {
-        /* do nothing */
-    }
-
-    private void addPrinterInternal(PrinterInfo printer) {
-        if (mHistoricalPrinters.size() >= MAX_HISTORY_LENGTH) {
-            mHistoricalPrinters.remove(0);
-        }
-        mHistoricalPrinters.add(new PrinterRecord(printer));
-    }
-
-    private void computeFavoritePrinters() {
-        Map<PrinterId, PrinterRecord> recordMap =
-                new ArrayMap<PrinterId, PrinterRecord>();
-
-        // Recompute the weights.
-        float currentWeight = 1.0f;
-        final int printerCount = mHistoricalPrinters.size();
-        for (int i = printerCount - 1; i >= 0; i--) {
-            PrinterRecord record = mHistoricalPrinters.get(i);
-            record.weight = currentWeight;
-            // Aggregate weight for the same printer
-            PrinterRecord oldRecord = recordMap.put(record.printer.getId(), record);
-            if (oldRecord != null) {
-                record.weight += oldRecord.weight;
-            }
-            currentWeight *= WEIGHT_DECAY_COEFFICIENT;
-        }
-
-        // Copy the unique printer records with computed weights.
-        mFavoritePrinters.addAll(recordMap.values());
-
-        // Soft the favorite printers.
-        Collections.sort(mFavoritePrinters);
-    }
-
-    private final class PrinterRecord implements Comparable<PrinterRecord> {
-        public final PrinterInfo printer;
-        public float weight;
-
-        public PrinterRecord(PrinterInfo printer) {
-            this.printer = printer;
-        }
-
-        @Override
-        public int compareTo(PrinterRecord another) {
-            return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
-        }
-    }
-
-    private final class PersistenceManager {
-        private static final String PERSIST_FILE_NAME = "printer_history.xml";
-
-        private static final String TAG_PRINTERS = "printers";
-
-        private static final String TAG_PRINTER = "printer";
-        private static final String TAG_PRINTER_ID = "printerId";
-
-        private static final String ATTR_LOCAL_ID = "localId";
-        private static final String ATTR_SERVICE_NAME = "serviceName";
-
-        private static final String ATTR_NAME = "name";
-        private static final String ATTR_DESCRIPTION = "description";
-        private static final String ATTR_STATUS = "status";
-
-        private final AtomicFile mStatePersistFile;
-
-        private PersistenceManager(Context context) {
-            mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
-                    PERSIST_FILE_NAME));
-        }
-
-        @SuppressWarnings("unchecked")
-        public void writeState() {
-
-            new AsyncTask<List<PrinterRecord>, Void, Void>() {
-                @Override
-                protected Void doInBackground(List<PrinterRecord>... printers) {
-                    doWriteState(printers[0]);
-                    return null;
-                }
-
-                @Override
-                protected void onPostExecute(Void result) {
-                    notifyChanged();
-                }
-
-            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,
-                    new ArrayList<PrinterRecord>(mHistoricalPrinters));
-        }
-
-        private void doWriteState(List<PrinterRecord> printers) {
-            FileOutputStream out = null;
-            try {
-                out = mStatePersistFile.startWrite();
-
-                XmlSerializer serializer = new FastXmlSerializer();
-                serializer.setOutput(out, "utf-8");
-                serializer.startDocument(null, true);
-                serializer.startTag(null, TAG_PRINTERS);
-
-                final int printerCount = printers.size();
-                for (int i = printerCount - 1; i >= 0; i--) {
-                    PrinterInfo printer = printers.get(i).printer;
-
-                    serializer.startTag(null, TAG_PRINTER);
-
-                    serializer.attribute(null, ATTR_NAME, printer.getName());
-                    serializer.attribute(null, ATTR_STATUS, String.valueOf(printer.getStatus()));
-                    String description = printer.getDescription();
-                    if (description != null) {
-                        serializer.attribute(null, ATTR_DESCRIPTION, description);
-                    }
-
-                    PrinterId printerId = printer.getId();
-                    serializer.startTag(null, TAG_PRINTER_ID);
-                    serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
-                    serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
-                            .flattenToString());
-                    serializer.endTag(null, TAG_PRINTER_ID);
-
-                    serializer.endTag(null, TAG_PRINTER);
-
-                    if (DEBUG) {
-                        Log.i(LOG_TAG, "[PERSISTED] " + printer);
-                    }
-                }
-
-                serializer.endTag(null, TAG_PRINTERS);
-                serializer.endDocument();
-                mStatePersistFile.finishWrite(out);
-
-                if (DEBUG) {
-                    Log.i(LOG_TAG, "[PERSIST END]");
-                }
-            } catch (IOException ioe) {
-                Slog.w(LOG_TAG, "Failed to write printer history, restoring backup.", ioe);
-                mStatePersistFile.failWrite(out);
-            } finally {
-                IoUtils.closeQuietly(out);
-            }
-        }
-
-        public void readStateLocked() {
-            FileInputStream in = null;
-            try {
-                in = mStatePersistFile.openRead();
-            } catch (FileNotFoundException e) {
-                Log.i(LOG_TAG, "No existing printer history.");
-                return;
-            }
-            try {
-                XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(in, null);
-                parseState(parser);
-            } catch (IllegalStateException ise) {
-                Slog.w(LOG_TAG, "Failed parsing ", ise);
-            } catch (NullPointerException npe) {
-                Slog.w(LOG_TAG, "Failed parsing ", npe);
-            } catch (NumberFormatException nfe) {
-                Slog.w(LOG_TAG, "Failed parsing ", nfe);
-            } catch (XmlPullParserException xppe) {
-                Slog.w(LOG_TAG, "Failed parsing ", xppe);
-            } catch (IOException ioe) {
-                Slog.w(LOG_TAG, "Failed parsing ", ioe);
-            } catch (IndexOutOfBoundsException iobe) {
-                Slog.w(LOG_TAG, "Failed parsing ", iobe);
-            } finally {
-                IoUtils.closeQuietly(in);
-            }
-            notifyChanged();
-        }
-
-        private void parseState(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            parser.next();
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.START_TAG, TAG_PRINTERS);
-            parser.next();
-
-            while (parsePrinter(parser)) {
-                parser.next();
-            }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_PRINTERS);
-
-            // We were reading the new records first and appended them first,
-            // hence the historical list is in a reversed order, so fix that.
-            Collections.reverse(mHistoricalPrinters);
-        }
-
-        private boolean parsePrinter(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            skipEmptyTextTags(parser);
-            if (!accept(parser, XmlPullParser.START_TAG, TAG_PRINTER)) {
-                return false;
-            }
-
-            String name = parser.getAttributeValue(null, ATTR_NAME);
-            String description = parser.getAttributeValue(null, ATTR_DESCRIPTION);
-            final int status = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATUS));
-
-            parser.next();
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID);
-            String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
-            ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
-                    null, ATTR_SERVICE_NAME));
-            PrinterId printerId =  new PrinterId(service, localId);
-            parser.next();
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
-            parser.next();
-
-            PrinterInfo.Builder builder = new PrinterInfo.Builder(printerId, name, status);
-            builder.setDescription(description);
-            PrinterInfo printer = builder.create();
-
-            addPrinterInternal(printer);
-
-            if (DEBUG) {
-                Log.i(LOG_TAG, "[RESTORED] " + printer);
-            }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_PRINTER);
-
-            return true;
-        }
-
-        private void expect(XmlPullParser parser, int type, String tag)
-                throws IOException, XmlPullParserException {
-            if (!accept(parser, type, tag)) {
-                throw new XmlPullParserException("Exepected event: " + type
-                        + " and tag: " + tag + " but got event: " + parser.getEventType()
-                        + " and tag:" + parser.getName());
-            }
-        }
-
-        private void skipEmptyTextTags(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            while (accept(parser, XmlPullParser.TEXT, null)
-                    && "\n".equals(parser.getText())) {
-                parser.next();
-            }
-        }
-
-        private boolean accept(XmlPullParser parser, int type, String tag)
-                throws IOException, XmlPullParserException {
-            if (parser.getEventType() != type) {
-                return false;
-            }
-            if (tag != null) {
-                if (!tag.equals(parser.getName())) {
-                    return false;
-                }
-            } else if (parser.getName() != null) {
-                return false;
-            }
-            return true;
-        }
-    }
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
new file mode 100644
index 0000000..6bad5b3
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Loader;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.printspooler.PrintSpoolerService.PrinterDiscoverySession;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is responsible for loading printers by doing discovery
+ * and merging the discovered printers with the previously used ones.
+ */
+public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
+    private static final String LOG_TAG = "FusedPrintersProvider";
+
+    private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
+
+    private static final double WEIGHT_DECAY_COEFFICIENT = 0.95f;
+
+    private static final int MAX_HISTORY_LENGTH = 50;
+
+    private static final int MAX_HISTORICAL_PRINTER_COUNT = 4;
+
+    private final Map<PrinterId, PrinterInfo> mPrinters =
+            new LinkedHashMap<PrinterId, PrinterInfo>();
+
+    private final PersistenceManager mPersistenceManager;
+
+    private PrinterDiscoverySession mDiscoverySession;
+
+    private List<PrinterInfo> mFavoritePrinters;
+
+    public FusedPrintersProvider(Context context) {
+        super(context);
+        mPersistenceManager = new PersistenceManager(context);
+    }
+
+    public void addHistoricalPrinter(PrinterInfo printer) {
+        mPersistenceManager.addPrinterAndWritePrinterHistory(printer);
+    }
+
+    public List<PrinterInfo> getPrinters() {
+        return new ArrayList<PrinterInfo>(mPrinters.values());
+    }
+
+    @Override
+    public void deliverResult(List<PrinterInfo> printers) {
+        if (isStarted()) {
+            super.deliverResult(printers);
+        }
+    }
+
+    @Override
+    protected void onStartLoading() {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "onStartLoading()");
+        }
+        // The contract is that if we already have a valid,
+        // result the we have to deliver it immediately.
+        if (!mPrinters.isEmpty()) {
+            deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+        }
+        // If the data has changed since the last load
+        // or is not available, start a load.
+        if (takeContentChanged() || mPrinters.isEmpty()) {
+            onForceLoad();
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "onStopLoading()");
+        }
+        onCancelLoad();
+    }
+
+    @Override
+    protected void onForceLoad() {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "onForceLoad()");
+        }
+        onCancelLoad();
+        loadInternal();
+    }
+
+    private void loadInternal() {
+        if (mDiscoverySession == null) {
+            mDiscoverySession = new MyPrinterDiscoverySession();
+            mPersistenceManager.readPrinterHistory();
+        }
+        if (mPersistenceManager.isReadHistoryCompleted()
+                && !mDiscoverySession.isStarted()) {
+            final int favoriteCount = Math.min(MAX_HISTORICAL_PRINTER_COUNT,
+                    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);
+        }
+    }
+
+    @Override
+    protected boolean onCancelLoad() {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "onCancelLoad()");
+        }
+        return cancelInternal();
+    }
+
+    private boolean cancelInternal() {
+        if (mDiscoverySession != null && mDiscoverySession.isStarted()) {
+            mDiscoverySession.stopPrinterDiscovery();
+            return true;
+        } else if (mPersistenceManager.isReadHistoryInProgress()) {
+            return mPersistenceManager.stopReadPrinterHistory();
+        }
+        return false;
+    }
+
+    @Override
+    protected void onReset() {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "onReset()");
+        }
+        onStopLoading();
+        mPrinters.clear();
+        if (mDiscoverySession != null) {
+            mDiscoverySession.destroy();
+            mDiscoverySession = null;
+        }
+    }
+
+    @Override
+    protected void onAbandon() {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "onAbandon()");
+        }
+        onStopLoading();
+    }
+
+    public void refreshPrinter(PrinterId printerId) {
+        if (isStarted() && mDiscoverySession != null && mDiscoverySession.isStarted()) {
+            mDiscoverySession.requestPrinterUpdated(printerId);
+        }
+    }
+
+    private final class MyPrinterDiscoverySession extends PrinterDiscoverySession {
+
+        @Override
+        public void onPrintersAdded(List<PrinterInfo> printers) {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersAdded()");
+            }
+            boolean printersAdded = false;
+            final int addedPrinterCount = printers.size();
+            for (int i = 0; i < addedPrinterCount; i++) {
+                PrinterInfo printer = printers.get(i);
+                if (!mPrinters.containsKey(printer.getId())) {
+                    mPrinters.put(printer.getId(), printer);
+                    printersAdded = true;
+                }
+            }
+            if (printersAdded) {
+                deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+            }
+        }
+
+        @Override
+        public void onPrintersRemoved(List<PrinterId> printerIds) {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersRemoved()");
+            }
+            boolean removedPrinters = false;
+            final int removedPrinterCount = printerIds.size();
+            for (int i = 0; i < removedPrinterCount; i++) {
+                PrinterId removedPrinterId = printerIds.get(i);
+                if (mPrinters.remove(removedPrinterId) != null) {
+                    removedPrinters = true;
+                }
+            }
+            if (removedPrinters) {
+                deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+            }
+        }
+
+        @Override
+        public void onPrintersUpdated(List<PrinterInfo> printers) {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersUpdated()");
+            }
+            boolean updatedPrinters = false;
+            final int updatedPrinterCount = printers.size();
+            for (int i = 0; i < updatedPrinterCount; i++) {
+                PrinterInfo updatedPrinter = printers.get(i);
+                if (mPrinters.containsKey(updatedPrinter.getId())) {
+                    mPrinters.put(updatedPrinter.getId(), updatedPrinter);
+                    updatedPrinters = true;
+                }
+            }
+            if (updatedPrinters) {
+                deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+            }
+        }
+    }
+
+    private final class PersistenceManager {
+        private static final String PERSIST_FILE_NAME = "printer_history.xml";
+
+        private static final String TAG_PRINTERS = "printers";
+
+        private static final String TAG_PRINTER = "printer";
+        private static final String TAG_PRINTER_ID = "printerId";
+
+        private static final String ATTR_LOCAL_ID = "localId";
+        private static final String ATTR_SERVICE_NAME = "serviceName";
+
+        private static final String ATTR_NAME = "name";
+        private static final String ATTR_DESCRIPTION = "description";
+        private static final String ATTR_STATUS = "status";
+
+        private final AtomicFile mStatePersistFile;
+
+        private List<PrinterInfo> mHistoricalPrinters;
+
+        private boolean mReadHistoryCompleted;
+        private boolean mReadHistoryInProgress;
+
+        private final AsyncTask<Void, Void, List<PrinterInfo>> mReadTask =
+                new AsyncTask<Void, Void, List<PrinterInfo>>() {
+            @Override
+            protected List<PrinterInfo> doInBackground(Void... args) {
+               return doReadPrinterHistory();
+            }
+
+            @Override
+            protected void onPostExecute(List<PrinterInfo> printers) {
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "read history completed");
+                }
+
+                mHistoricalPrinters = printers;
+
+                // Compute the favorite printers.
+                mFavoritePrinters = computeFavoritePrinters(printers);
+
+                // We want the first few favorite printers on top of the list.
+                final int favoriteCount = Math.min(mFavoritePrinters.size(),
+                        MAX_HISTORICAL_PRINTER_COUNT);
+                for (int i = 0; i < favoriteCount; i++) {
+                    PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
+                    mPrinters.put(favoritePrinter.getId(), favoritePrinter);
+                }
+
+                mReadHistoryInProgress = false;
+                mReadHistoryCompleted = true;
+
+                loadInternal();
+            }
+
+            private List<PrinterInfo> doReadPrinterHistory() {
+                FileInputStream in = null;
+                try {
+                    in = mStatePersistFile.openRead();
+                } catch (FileNotFoundException fnfe) {
+                    Log.i(LOG_TAG, "No existing printer history.");
+                    return new ArrayList<PrinterInfo>();
+                }
+                try {
+                    List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+                    XmlPullParser parser = Xml.newPullParser();
+                    parser.setInput(in, null);
+                    parseState(parser, printers);
+                    return printers;
+                } catch (IllegalStateException ise) {
+                    Slog.w(LOG_TAG, "Failed parsing ", ise);
+                } catch (NullPointerException npe) {
+                    Slog.w(LOG_TAG, "Failed parsing ", npe);
+                } catch (NumberFormatException nfe) {
+                    Slog.w(LOG_TAG, "Failed parsing ", nfe);
+                } catch (XmlPullParserException xppe) {
+                    Slog.w(LOG_TAG, "Failed parsing ", xppe);
+                } catch (IOException ioe) {
+                    Slog.w(LOG_TAG, "Failed parsing ", ioe);
+                } catch (IndexOutOfBoundsException iobe) {
+                    Slog.w(LOG_TAG, "Failed parsing ", iobe);
+                } finally {
+                    IoUtils.closeQuietly(in);
+                }
+
+                return Collections.emptyList();
+            }
+
+            private void parseState(XmlPullParser parser, List<PrinterInfo> outPrinters)
+                    throws IOException, XmlPullParserException {
+                parser.next();
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.START_TAG, TAG_PRINTERS);
+                parser.next();
+
+                while (parsePrinter(parser, outPrinters)) {
+                    // Be nice and respond to cancellation
+                    if (isCancelled()) {
+                        return;
+                    }
+                    parser.next();
+                }
+
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_PRINTERS);
+            }
+
+            private boolean parsePrinter(XmlPullParser parser, List<PrinterInfo> outPrinters)
+                    throws IOException, XmlPullParserException {
+                skipEmptyTextTags(parser);
+                if (!accept(parser, XmlPullParser.START_TAG, TAG_PRINTER)) {
+                    return false;
+                }
+
+                String name = parser.getAttributeValue(null, ATTR_NAME);
+                String description = parser.getAttributeValue(null, ATTR_DESCRIPTION);
+                final int status = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATUS));
+
+                parser.next();
+
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID);
+                String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
+                ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
+                        null, ATTR_SERVICE_NAME));
+                PrinterId printerId =  new PrinterId(service, localId);
+                parser.next();
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
+                parser.next();
+
+                PrinterInfo.Builder builder = new PrinterInfo.Builder(printerId, name, status);
+                builder.setDescription(description);
+                PrinterInfo printer = builder.create();
+
+                outPrinters.add(printer);
+
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "[RESTORED] " + printer);
+                }
+
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_PRINTER);
+
+                return true;
+            }
+
+            private void expect(XmlPullParser parser, int type, String tag)
+                    throws IOException, XmlPullParserException {
+                if (!accept(parser, type, tag)) {
+                    throw new XmlPullParserException("Exepected event: " + type
+                            + " and tag: " + tag + " but got event: " + parser.getEventType()
+                            + " and tag:" + parser.getName());
+                }
+            }
+
+            private void skipEmptyTextTags(XmlPullParser parser)
+                    throws IOException, XmlPullParserException {
+                while (accept(parser, XmlPullParser.TEXT, null)
+                        && "\n".equals(parser.getText())) {
+                    parser.next();
+                }
+            }
+
+            private boolean accept(XmlPullParser parser, int type, String tag)
+                    throws IOException, XmlPullParserException {
+                if (parser.getEventType() != type) {
+                    return false;
+                }
+                if (tag != null) {
+                    if (!tag.equals(parser.getName())) {
+                        return false;
+                    }
+                } else if (parser.getName() != null) {
+                    return false;
+                }
+                return true;
+            }
+        };
+
+        private final AsyncTask<List<PrinterInfo>, Void, Void> mWriteTask =
+                new AsyncTask<List<PrinterInfo>, Void, Void>() {
+            @Override
+            protected Void doInBackground(List<PrinterInfo>... printers) {
+                doWritePrinterHistory(printers[0]);
+                return null;
+            }
+
+            private void doWritePrinterHistory(List<PrinterInfo> printers) {
+                FileOutputStream out = null;
+                try {
+                    out = mStatePersistFile.startWrite();
+
+                    XmlSerializer serializer = new FastXmlSerializer();
+                    serializer.setOutput(out, "utf-8");
+                    serializer.startDocument(null, true);
+                    serializer.startTag(null, TAG_PRINTERS);
+
+                    final int printerCount = printers.size();
+                    for (int i = 0; i < printerCount; i++) {
+                        PrinterInfo printer = printers.get(i);
+
+                        serializer.startTag(null, TAG_PRINTER);
+
+                        serializer.attribute(null, ATTR_NAME, printer.getName());
+                        serializer.attribute(null, ATTR_STATUS, String.valueOf(
+                                printer.getStatus()));
+                        String description = printer.getDescription();
+                        if (description != null) {
+                            serializer.attribute(null, ATTR_DESCRIPTION, description);
+                        }
+
+                        PrinterId printerId = printer.getId();
+                        serializer.startTag(null, TAG_PRINTER_ID);
+                        serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
+                        serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
+                                .flattenToString());
+                        serializer.endTag(null, TAG_PRINTER_ID);
+
+                        serializer.endTag(null, TAG_PRINTER);
+
+                        if (DEBUG) {
+                            Log.i(LOG_TAG, "[PERSISTED] " + printer);
+                        }
+                    }
+
+                    serializer.endTag(null, TAG_PRINTERS);
+                    serializer.endDocument();
+                    mStatePersistFile.finishWrite(out);
+
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "[PERSIST END]");
+                    }
+                } catch (IOException ioe) {
+                    Slog.w(LOG_TAG, "Failed to write printer history, restoring backup.", ioe);
+                    mStatePersistFile.failWrite(out);
+                } finally {
+                    IoUtils.closeQuietly(out);
+                }
+            }
+        };
+
+        private PersistenceManager(Context context) {
+            mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
+                    PERSIST_FILE_NAME));
+        }
+
+        public boolean isReadHistoryInProgress() {
+            return mReadHistoryInProgress;
+        }
+
+        public boolean isReadHistoryCompleted() {
+            return mReadHistoryCompleted;
+        }
+
+        public boolean stopReadPrinterHistory() {
+            return mReadTask.cancel(true);
+        }
+
+        public void readPrinterHistory() {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "read history started");
+            }
+            mReadHistoryInProgress = true;
+            mReadTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+        }
+
+        @SuppressWarnings("unchecked")
+        public void addPrinterAndWritePrinterHistory(PrinterInfo printer) {
+            if (mHistoricalPrinters.size() >= MAX_HISTORY_LENGTH) {
+                mHistoricalPrinters.remove(0);
+            }
+            mHistoricalPrinters.add(printer);
+            mWriteTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, mHistoricalPrinters);
+        }
+
+        private List<PrinterInfo> computeFavoritePrinters(List<PrinterInfo> printers) {
+            Map<PrinterId, PrinterRecord> recordMap =
+                    new ArrayMap<PrinterId, PrinterRecord>();
+
+            // Recompute the weights.
+            float currentWeight = 1.0f;
+            final int printerCount = printers.size();
+            for (int i = printerCount - 1; i >= 0; i--) {
+                PrinterInfo printer = printers.get(i);
+                // Aggregate weight for the same printer
+                PrinterRecord record = recordMap.get(printer.getId());
+                if (record == null) {
+                    record = new PrinterRecord(printer);
+                    recordMap.put(printer.getId(), record);
+                }
+                record.weight += currentWeight;
+                currentWeight *= WEIGHT_DECAY_COEFFICIENT;
+            }
+
+            // Soft the favorite printers.
+            List<PrinterRecord> favoriteRecords = new ArrayList<PrinterRecord>(
+                    recordMap.values());
+            Collections.sort(favoriteRecords);
+
+            // Write the favorites to the output.
+            final int favoriteCount = favoriteRecords.size();
+            List<PrinterInfo> favoritePrinters = new ArrayList<PrinterInfo>(favoriteCount);
+            for (int i = 0; i < favoriteCount; i++) {
+                PrinterInfo printer = favoriteRecords.get(i).printer;
+                favoritePrinters.add(printer);
+            }
+
+            return favoritePrinters;
+        }
+
+        private final class PrinterRecord implements Comparable<PrinterRecord> {
+            public final PrinterInfo printer;
+            public float weight;
+
+            public PrinterRecord(PrinterInfo printer) {
+                this.printer = printer;
+            }
+
+            @Override
+            public int compareTo(PrinterRecord another) {
+                return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
+            }
+        }
+    }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index f8e9f43..d3dd8c9 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -18,13 +18,17 @@
 
 import android.app.Activity;
 import android.app.Dialog;
+import android.app.LoaderManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.Loader;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.DataSetObserver;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -39,9 +43,11 @@
 import android.print.PageRange;
 import android.print.PrintAttributes;
 import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
 import android.print.PrintDocumentAdapter;
 import android.print.PrintDocumentInfo;
 import android.print.PrintJobInfo;
+import android.print.PrintManager;
 import android.print.PrinterCapabilitiesInfo;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
@@ -69,6 +75,14 @@
 import android.widget.Spinner;
 import android.widget.TextView;
 
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -93,15 +107,32 @@
     public static final String EXTRA_PRINT_ATTRIBUTES = "printAttributes";
     public static final String EXTRA_PRINT_JOB_ID = "printJobId";
 
-    private static final int CONTROLLER_STATE_INITIALIZED = 1;
-    private static final int CONTROLLER_STATE_STARTED = 2;
-    private static final int CONTROLLER_STATE_LAYOUT_STARTED = 3;
-    private static final int CONTROLLER_STATE_LAYOUT_COMPLETED = 4;
-    private static final int CONTROLLER_STATE_WRITE_STARTED = 5;
-    private static final int CONTROLLER_STATE_WRITE_COMPLETED = 6;
-    private static final int CONTROLLER_STATE_FINISHED = 7;
-    private static final int CONTROLLER_STATE_FAILED = 8;
-    private static final int CONTROLLER_STATE_CANCELLED = 9;
+    public static final String INTENT_EXTRA_PRINTER_ID = "INTENT_EXTRA_PRINTER_ID";
+
+    private static final int LOADER_ID_PRINTERS_LOADER = 1;
+
+    private static final int DEST_ADAPTER_MIN_ITEM_COUNT = 2;
+    private static final int DEST_ADAPTER_MAX_ITEM_COUNT = 9;
+
+    private static final int DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS = 0;
+    private static final int DEST_ADAPTER_POSITION_SAVE_AS_PDF = 1;
+
+    private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
+    private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
+    private static final int DEST_ADAPTER_ITEM_ID_SEARCHING_FOR_PRINTERS = Integer.MAX_VALUE - 2;
+
+    private static final int ACTIVITY_REQUEST_CREATE_FILE = 1;
+    private static final int ACTIVITY_REQUEST_SELECT_PRINTER = 2;
+
+    private static final int CONTROLLER_STATE_FINISHED = 1;
+    private static final int CONTROLLER_STATE_FAILED = 2;
+    private static final int CONTROLLER_STATE_CANCELLED = 3;
+    private static final int CONTROLLER_STATE_INITIALIZED = 4;
+    private static final int CONTROLLER_STATE_STARTED = 5;
+    private static final int CONTROLLER_STATE_LAYOUT_STARTED = 6;
+    private static final int CONTROLLER_STATE_LAYOUT_COMPLETED = 7;
+    private static final int CONTROLLER_STATE_WRITE_STARTED = 8;
+    private static final int CONTROLLER_STATE_WRITE_COMPLETED = 9;
 
     private static final int EDITOR_STATE_INITIALIZED = 1;
     private static final int EDITOR_STATE_CONFIRMED_PRINT = 2;
@@ -109,6 +140,7 @@
     private static final int EDITOR_STATE_CANCELLED = 4;
 
     private static final int MIN_COPIES = 1;
+    private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);
 
     private static final Pattern PATTERN_DIGITS = Pattern.compile("\\d");
 
@@ -135,10 +167,6 @@
     private Document mDocument;
     private PrintController mController;
 
-    private AvailablePrinterProvider mAvailablePrinters;
-
-    private FavoritePrinterProvider mFavoritePrinters;
-
     private int mPrintJobId;
 
     private IBinder mIPrintDocumentAdapter;
@@ -148,9 +176,6 @@
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
-        setContentView(R.layout.print_job_config_activity_container);
-
-        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
 
         Bundle extras = getIntent().getExtras();
 
@@ -169,15 +194,17 @@
             mCurrPrintAttributes.copyFrom(attributes);
         }
 
-        // TODO: Use history
-        mAvailablePrinters = new AvailablePrinterProvider(this, null);
-        mFavoritePrinters = new FavoritePrinterProvider(this);
+        setContentView(R.layout.print_job_config_activity_container);
+
+        // TODO: This should be on the style
+        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
+
 
         mEditor = new Editor();
         mDocument = new Document();
         mController = new PrintController(new RemotePrintDocumentAdapter(
                 IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
-                PrintSpooler.peekInstance().generateFileForPrintJob(mPrintJobId)));
+                PrintSpoolerService.peekInstance().generateFileForPrintJob(mPrintJobId)));
 
         try {
             mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
@@ -191,26 +218,6 @@
     }
 
     @Override
-    protected void onResume() {
-        super.onResume();
-        // TODO: Polish this
-        if (!mEditor.isPrintConfirmed()) {
-            mAvailablePrinters.startLoadData();
-            mFavoritePrinters.startLoadData();
-        }
-    }
-
-    @Override
-    protected void onPause() {
-        // TODO: Polish this
-        if (!mEditor.isPrintConfirmed()) {
-            mAvailablePrinters.stopLoadData();
-            mFavoritePrinters.stopLoadData();
-        }
-        super.onPause();
-    }
-
-    @Override
     protected void onDestroy() {
         // We can safely do the work in here since at this point
         // the system is bound to our (spooler) process which
@@ -219,10 +226,10 @@
             mController.finish();
         }
         if (mEditor.isPrintConfirmed() && mController.isFinished()) {
-            PrintSpooler.peekInstance().setPrintJobState(mPrintJobId,
+            PrintSpoolerService.peekInstance().setPrintJobState(mPrintJobId,
                     PrintJobInfo.STATE_QUEUED, null);
         } else {
-            PrintSpooler.peekInstance().setPrintJobState(mPrintJobId,
+            PrintSpoolerService.peekInstance().setPrintJobState(mPrintJobId,
                     PrintJobInfo.STATE_CANCELED, null);
         }
         mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
@@ -333,13 +340,13 @@
 
         public void update() {
             if (!printAttributesChanged()) {
-                // If the attributes changes, then we do not do a layout but may
+                // If the attributes changed, then we do not do a layout but may
                 // have to ask the app to write some pages. Hence, pretend layout
                 // completed and nothing changed, so we handle writing as usual.
                 handleOnLayoutFinished(mDocument.info, false, mRequestCounter.get());
             } else {
-                PrintSpooler.peekInstance().setPrintJobAttributesNoPersistence(mPrintJobId,
-                        mCurrPrintAttributes);
+                PrintSpoolerService.peekInstance().setPrintJobAttributesNoPersistence(
+                        mPrintJobId, mCurrPrintAttributes);
 
                 mMetadata.putBoolean(PrintDocumentAdapter.METADATA_KEY_PRINT_PREVIEW,
                         !mEditor.isPrintConfirmed());
@@ -378,7 +385,7 @@
             final boolean infoChanged = !info.equals(mDocument.info);
             if (infoChanged) {
                 mDocument.info = info;
-                PrintSpooler.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
+                PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
                         mPrintJobId, info);
             }
 
@@ -465,12 +472,12 @@
             if (Arrays.equals(mDocument.pages, mRequestedPages)) {
                 // We got a document with exactly the pages we wanted. Hence,
                 // the printer has to print all pages in the data.
-                PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
                         ALL_PAGES_ARRAY);
             } else if (Arrays.equals(mDocument.pages, ALL_PAGES_ARRAY)) {
                 // We requested specific pages but got all of them. Hence,
                 // the printer has to print only the requested pages.
-                PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
                         mRequestedPages);
             } else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
                 // We requested specific pages and got more but not all pages.
@@ -480,7 +487,7 @@
                 final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
                 PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
                 PageRangeUtils.offsetStart(offsetPages, offset);
-                PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
                         offsetPages);
             } else if (Arrays.equals(mRequestedPages, ALL_PAGES_ARRAY)
                     && mDocument.pages.length == 1 && mDocument.pages[0].getStart() == 0
@@ -488,7 +495,7 @@
                 // We requested all pages via the special constant and got all
                 // of them as an explicit enumeration. Hence, the printer has
                 // to print only the requested pages.
-                PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+                PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
                         mDocument.pages);
             } else {
                 // We did not get the pages we requested, then the application
@@ -500,7 +507,16 @@
             }
 
             if (mEditor.isDone()) {
-                PrintJobConfigActivity.this.finish();
+                if (mEditor.isPrintingToPdf()) {
+                    PrintJobInfo printJob = PrintSpoolerService.peekInstance()
+                            .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
+                    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+                    intent.setType("application/pdf");
+                    intent.putExtra(Intent.EXTRA_TITLE, printJob.getLabel());
+                    startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
+                } else {
+                    PrintJobConfigActivity.this.finish();
+                }
             }
         }
 
@@ -607,33 +623,111 @@
         }
     }
 
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case ACTIVITY_REQUEST_CREATE_FILE: {
+                if (data != null) {
+                    Uri uri = data.getData();
+                    writePrintJobDataAndFinish(uri);
+                } else {
+                    mEditor.showUi(Editor.UI_EDITING_PRINT_JOB,
+                            new Runnable() {
+                        @Override
+                        public void run() {
+                            mEditor.initialize();
+                            mEditor.bindUi();
+                            mEditor.updateUi();
+                        }
+                    });
+                }
+            } break;
+
+            case ACTIVITY_REQUEST_SELECT_PRINTER: {
+                if (resultCode == RESULT_OK) {
+                    PrinterId printerId = (PrinterId) data.getParcelableExtra(
+                            INTENT_EXTRA_PRINTER_ID);
+                    // TODO: Make sure the selected printer is in the shown list.
+                    mEditor.selectPrinter(printerId);
+                }
+            } break;
+        }
+    }
+
+    private void writePrintJobDataAndFinish(final Uri uri) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                InputStream in = null;
+                OutputStream out = null;
+                try {
+                    PrintJobInfo printJob = PrintSpoolerService.peekInstance()
+                            .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
+                    if (printJob == null) {
+                        return null;
+                    }
+                    File file = PrintSpoolerService.peekInstance()
+                            .generateFileForPrintJob(mPrintJobId);
+                    in = new FileInputStream(file);
+                    out = getContentResolver().openOutputStream(uri);
+                    final byte[] buffer = new byte[8192];
+                    while (true) {
+                        final int readByteCount = in.read(buffer);
+                        if (readByteCount < 0) {
+                            break;
+                        }
+                        out.write(buffer, 0, readByteCount);
+                    }
+                } catch (FileNotFoundException fnfe) {
+                    Log.e(LOG_TAG, "Error writing print job data!", fnfe);
+                } catch (IOException ioe) {
+                    Log.e(LOG_TAG, "Error writing print job data!", ioe);
+                } finally {
+                    IoUtils.closeQuietly(in);
+                    IoUtils.closeQuietly(out);
+                }
+                return null;
+            }
+
+            @Override
+            public void onPostExecute(Void result) {
+                mEditor.cancel();
+                PrintJobConfigActivity.this.finish();
+            }
+        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+    }
+
     private final class Editor {
-        private final EditText mCopiesEditText;
+        private static final int UI_NONE = 0;
+        private static final int UI_EDITING_PRINT_JOB = 1;
+        private static final int UI_GENERATING_PRINT_JOB = 2;
 
-        private final TextView mRangeTitle;
-        private final EditText mRangeEditText;
+        private EditText mCopiesEditText;
 
-        private final Spinner mDestinationSpinner;
+        private TextView mRangeTitle;
+        private EditText mRangeEditText;
+
+        private Spinner mDestinationSpinner;
         private final DestinationAdapter mDestinationSpinnerAdapter;
 
-        private final Spinner mMediaSizeSpinner;
+        private Spinner mMediaSizeSpinner;
         private final ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
 
-        private final Spinner mColorModeSpinner;
+        private Spinner mColorModeSpinner;
         private final ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
 
-        private final Spinner mOrientationSpinner;
+        private Spinner mOrientationSpinner;
         private final  ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
 
-        private final Spinner mRangeOptionsSpinner;
+        private Spinner mRangeOptionsSpinner;
         private final ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
 
         private final SimpleStringSplitter mStringCommaSplitter =
                 new SimpleStringSplitter(',');
 
-        private final View mContentContainer;
+        private View mContentContainer;
 
-        private final Button mPrintButton;
+        private Button mPrintButton;
 
         private final OnItemSelectedListener mOnItemSelectedListener =
                 new AdapterView.OnItemSelectedListener() {
@@ -644,18 +738,31 @@
                         mIgnoreNextDestinationChange = false;
                         return;
                     }
+                    if (id == DEST_ADAPTER_ITEM_ID_ALL_PRINTERS) {
+                        mIgnoreNextDestinationChange = true;
+                        mDestinationSpinner.setSelection(0);
+                        Intent intent = new Intent(PrintJobConfigActivity.this,
+                                SelectPrinterActivity.class);
+                        startActivityForResult(intent, ACTIVITY_REQUEST_SELECT_PRINTER);
+                        return;
+                    }
+                    mWaitingForPrinterCapabilities = false;
                     mCurrPrintAttributes.clear();
                     PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter
                             .getItem(position);
                     if (printer != null) {
-                        PrintSpooler.peekInstance().setPrintJobPrinterNoPersistence(
+                        PrintSpoolerService.peekInstance().setPrintJobPrinterNoPersistence(
                                 mPrintJobId, printer);
                         PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
                         if (capabilities == null) {
                             List<PrinterId> printerIds = new ArrayList<PrinterId>();
                             printerIds.add(printer.getId());
-                            final int index = mAvailablePrinters.getItemIndex(printer);
-                            mAvailablePrinters.refreshItem(index);
+                            FusedPrintersProvider printersLoader = (FusedPrintersProvider)
+                                    (Loader<?>) getLoaderManager().getLoader(
+                                            LOADER_ID_PRINTERS_LOADER);
+                            if (printersLoader != null) {
+                                printersLoader.refreshPrinter(printer.getId());
+                            }
                             mWaitingForPrinterCapabilities = true;
                             //TODO: We need a timeout for the update.
                         } else {
@@ -668,6 +775,31 @@
                             }
                         }
                     }
+
+                    // The printer changed so we want to start with a clean slate
+                    // for the print options and let them be populated from the
+                    // printer capabilities and use the printer defaults.
+                    if (!mMediaSizeSpinnerAdapter.isEmpty()) {
+                        mIgnoreNextMediaSizeChange = true;
+                        mMediaSizeSpinnerAdapter.clear();
+                    }
+                    if (!mColorModeSpinnerAdapter.isEmpty()) {
+                        mIgnoreNextColorModeChange = true;
+                        mColorModeSpinnerAdapter.clear();
+                    }
+                    if (!mOrientationSpinnerAdapter.isEmpty()) {
+                        mIgnoreNextOrientationChange = true;
+                        mOrientationSpinnerAdapter.clear();
+                    }
+                    if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
+                        mIgnoreNextRangeOptionChange = true;
+                        mRangeOptionsSpinner.setSelection(0);
+                    }
+                    if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
+                        mIgnoreNextCopiesChange = true;
+                        mCopiesEditText.setText(MIN_COPIES_STRING);
+                    }
+
                     updateUi();
                 } else if (spinner == mMediaSizeSpinner) {
                     if (mIgnoreNextMediaSizeChange) {
@@ -753,7 +885,8 @@
                 }
 
                 mCopiesEditText.setError(null);
-                PrintSpooler.peekInstance().setPrintJobCopiesNoPersistence(mPrintJobId, copies);
+                PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence(
+                        mPrintJobId, copies);
                 updateUi();
 
                 if (hadErrors && !hasErrors() && printAttributesChanged()) {
@@ -832,22 +965,25 @@
 
         private boolean mWaitingForPrinterCapabilities;
 
+        private int mCurrentUi = UI_NONE;
+
         public Editor() {
-            // Content container
-            mContentContainer = findViewById(R.id.content_container);
-
-            // Copies
-            mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
-            mCopiesEditText.setText(String.valueOf(MIN_COPIES));
-            PrintSpooler.peekInstance().setPrintJobCopiesNoPersistence(mPrintJobId, MIN_COPIES);
-            mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
-            mCopiesEditText.selectAll();
-
             // Destination.
-            mDestinationSpinnerAdapter = new DestinationAdapter(mAvailablePrinters);
+            mDestinationSpinnerAdapter = new DestinationAdapter();
             mDestinationSpinnerAdapter.registerDataSetObserver(new DataSetObserver() {
                 @Override
                 public void onChanged() {
+                    final int selectedPosition = mDestinationSpinner.getSelectedItemPosition();
+                    if (mDestinationSpinnerAdapter.getCount() > 0) {
+                        // Make sure we select the first printer if we have data.
+                        if (selectedPosition == AdapterView.INVALID_POSITION) {
+                            mDestinationSpinner.setSelection(0);
+                        }
+                    } else {
+                        // Make sure we select no printer if we have no data.
+                        mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
+                    }
+
                     // Maybe we did not have capabilities when the current printer was
                     // selected, but now the selected printer has capabilities. Generate
                     // a fake selection so the code in the selection change handling takes
@@ -855,13 +991,9 @@
                     if (mWaitingForPrinterCapabilities) {
                         mWaitingForPrinterCapabilities = false;
                         PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
-                        if (printer != null) {
-                            if (printer.getCapabilities() != null) {
-                                final int selectedPosition =
-                                        mDestinationSpinner.getSelectedItemPosition();
-                                mOnItemSelectedListener.onItemSelected(mDestinationSpinner, null,
-                                        selectedPosition, selectedPosition);
-                            }
+                        if (printer != null && printer.getCapabilities() != null) {
+                            mOnItemSelectedListener.onItemSelected(mDestinationSpinner, null,
+                                    selectedPosition, selectedPosition);
                         }
                     }
                     updateUi();
@@ -872,41 +1004,23 @@
                     updateUi();
                 }
             });
-            mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
-            mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
-            mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
 
             // Media size.
-            mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
             mMediaSizeSpinnerAdapter = new ArrayAdapter<SpinnerItem<MediaSize>>(
                     PrintJobConfigActivity.this,
                     R.layout.spinner_dropdown_item, R.id.title);
-            mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
-            mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
 
             // Color mode.
-            mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
             mColorModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
                     PrintJobConfigActivity.this,
                     R.layout.spinner_dropdown_item, R.id.title);
-            mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
-            mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
 
             // Orientation
-            mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
             mOrientationSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
                     PrintJobConfigActivity.this,
                     R.layout.spinner_dropdown_item, R.id.title);
-            mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
-            mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
-            // Range
-            mRangeTitle = (TextView) findViewById(R.id.page_range_title);
-            mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
-            mRangeEditText.addTextChangedListener(mRangeTextWatcher);
 
             // Range options
-            mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
             mRangeOptionsSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
                     PrintJobConfigActivity.this,
                     R.layout.spinner_dropdown_item, R.id.title);
@@ -919,26 +1033,28 @@
                 mRangeOptionsSpinnerAdapter.add(new SpinnerItem<Integer>(
                         rangeOptionsValues[i], rangeOptionsLabels[i]));
             }
-            mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
-            if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
-                mIgnoreNextRangeOptionChange = true;
-                mRangeOptionsSpinner.setSelection(0);
-            }
 
-            // Print button
-            mPrintButton = (Button) findViewById(R.id.print_button);
-            mPrintButton.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    mEditor.confirmPrint();
-                    mController.update();
-                    showGeneratingPrintJobUi();
-                }
-            });
-
+            showUi(UI_EDITING_PRINT_JOB, null);
+            bindUi();
             updateUi();
         }
 
+        public void selectPrinter(PrinterId printerId) {
+            final int printerCount = mDestinationSpinnerAdapter.getCount();
+            for (int i = 0; i < printerCount; i++) {
+                PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter.getItem(i);
+                if (printer.getId().equals(printerId)) {
+                    mDestinationSpinner.setSelection(i);
+                    return;
+                }
+            }
+        }
+
+        public boolean isPrintingToPdf() {
+            return mDestinationSpinner.getSelectedItem()
+                    == mDestinationSpinnerAdapter.mFakePdfPrinter;
+        }
+
         public boolean shouldCloseOnTouch(MotionEvent event) {
             if (event.getAction() != MotionEvent.ACTION_DOWN) {
                 return false;
@@ -966,19 +1082,104 @@
         }
 
         public boolean isShwoingGeneratingPrintJobUi() {
-            return (findViewById(R.id.content_generating) != null);
+            return (mCurrentUi == UI_GENERATING_PRINT_JOB);
         }
 
-        private void showGeneratingPrintJobUi() {
-            // Find everything we will shuffle around.
-            final ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
-            final View contentEditing = contentContainer.findViewById(R.id.content_editing);
-            final View contentGenerating = getLayoutInflater().inflate(
-                    R.layout.print_job_config_activity_content_generating,
-                    contentContainer, false);
+        public void showUi(int ui, final Runnable postSwitchCallback) {
+            if (ui == UI_NONE) {
+                throw new IllegalStateException("cannot remove the ui");
+            }
 
-            // Wire the cancel action.
-            Button cancelButton = (Button) contentGenerating.findViewById(R.id.cancel_button);
+            if (mCurrentUi == ui) {
+                return;
+            }
+
+            switch (mCurrentUi) {
+                case UI_NONE: {
+                    switch (ui) {
+                        case UI_EDITING_PRINT_JOB: {
+                            doUiSwitch(R.layout.print_job_config_activity_content_editing);
+                            registerPrintButtonClickListener();
+                            if (postSwitchCallback != null) {
+                                postSwitchCallback.run();
+                            }
+                        } break;
+
+                        case UI_GENERATING_PRINT_JOB: {
+                            doUiSwitch(R.layout.print_job_config_activity_content_generating);
+                            registerCancelButtonClickListener();
+                            if (postSwitchCallback != null) {
+                                postSwitchCallback.run();
+                            }
+                        } break;
+                    }
+                } break;
+
+                case UI_EDITING_PRINT_JOB: {
+                    switch (ui) {
+                        case UI_GENERATING_PRINT_JOB: {
+                            animateUiSwitch(R.layout.print_job_config_activity_content_generating,
+                                    new Runnable() {
+                                @Override
+                                public void run() {
+                                    registerCancelButtonClickListener();
+                                    if (postSwitchCallback != null) {
+                                        postSwitchCallback.run();
+                                    }
+                                }
+                            });
+                        } break;
+                    }
+                } break;
+
+                case UI_GENERATING_PRINT_JOB: {
+                    switch (ui) {
+                        case UI_EDITING_PRINT_JOB: {
+                            animateUiSwitch(R.layout.print_job_config_activity_content_editing,
+                                    new Runnable() {
+                                @Override
+                                public void run() {
+                                    registerPrintButtonClickListener();
+                                    if (postSwitchCallback != null) {
+                                        postSwitchCallback.run();
+                                    }
+                                }
+                            });
+                        } break;
+                    }
+                } break;
+            }
+
+            mCurrentUi = ui;
+        }
+
+        private void registerPrintButtonClickListener() {
+            Button printButton = (Button) findViewById(R.id.print_button);
+            printButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
+                    if (printer != null) {
+                        mEditor.confirmPrint();
+                        mController.update();
+                        if (!printer.equals(mDestinationSpinnerAdapter.mFakePdfPrinter)) {
+                            FusedPrintersProvider printersLoader = (FusedPrintersProvider)
+                                    (Loader<?>) getLoaderManager().getLoader(
+                                            LOADER_ID_PRINTERS_LOADER);
+                            if (printersLoader != null) {
+                                printersLoader.addHistoricalPrinter(printer);
+                            }
+                        }
+                    } else {
+                        mEditor.cancel();
+                        PrintJobConfigActivity.this.finish();
+                    }
+                }
+            });
+        }
+
+        private void registerCancelButtonClickListener() {
+            Button cancelButton = (Button) findViewById(R.id.cancel_button);
             cancelButton.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
@@ -988,24 +1189,38 @@
                     mEditor.cancel();
                 }
             });
+        }
+
+        private void doUiSwitch(int showLayoutId) {
+            ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
+            contentContainer.removeAllViews();
+            getLayoutInflater().inflate(showLayoutId, contentContainer, true);
+        }
+
+        private void animateUiSwitch(int showLayoutId, final Runnable postAnimateCommand) {
+            // Find everything we will shuffle around.
+            final ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
+            final View hidingView = contentContainer.getChildAt(0);
+            final View showingView = getLayoutInflater().inflate(showLayoutId,
+                    null, false);
 
             // First animation - fade out the old content.
-            contentEditing.animate().alpha(0.0f).withLayer().withEndAction(new Runnable() {
+            hidingView.animate().alpha(0.0f).withLayer().withEndAction(new Runnable() {
                 @Override
                 public void run() {
-                    contentEditing.setVisibility(View.INVISIBLE);
+                    hidingView.setVisibility(View.INVISIBLE);
 
                     // Prepare the new content with correct size and alpha.
-                    contentGenerating.setMinimumWidth(contentContainer.getWidth());
-                    contentGenerating.setAlpha(0.0f);
+                    showingView.setMinimumWidth(contentContainer.getWidth());
+                    showingView.setAlpha(0.0f);
 
-                    // Compute how to much shrink the container to fit around the new content.
+                    // Compute how to much shrink /stretch the content.
                     final int widthSpec = MeasureSpec.makeMeasureSpec(
-                            contentContainer.getWidth(), MeasureSpec.AT_MOST);
+                            contentContainer.getWidth(), MeasureSpec.UNSPECIFIED);
                     final int heightSpec = MeasureSpec.makeMeasureSpec(
-                            contentContainer.getHeight(), MeasureSpec.AT_MOST);
-                    contentGenerating.measure(widthSpec, heightSpec);
-                    final float scaleY = (float) contentGenerating.getMeasuredHeight()
+                            contentContainer.getHeight(), MeasureSpec.UNSPECIFIED);
+                    showingView.measure(widthSpec, heightSpec);
+                    final float scaleY = (float) showingView.getMeasuredHeight()
                             / (float) contentContainer.getHeight();
 
                     // Second animation - resize the container.
@@ -1016,10 +1231,16 @@
                             // Swap the old and the new content.
                             contentContainer.removeAllViews();
                             contentContainer.setScaleY(1.0f);
-                            contentContainer.addView(contentGenerating);
+                            contentContainer.addView(showingView);
 
                             // Third animation - show the new content.
-                            contentGenerating.animate().withLayer().alpha(1.0f);
+                            showingView.animate().withLayer().alpha(1.0f).withEndAction(
+                                    new Runnable() {
+                                @Override
+                                public void run() {
+                                    postAnimateCommand.run();
+                                }
+                            });
                         }
                     });
                 }
@@ -1028,10 +1249,6 @@
 
         public void initialize() {
             mEditorState = EDITOR_STATE_INITIALIZED;
-            if (mDestinationSpinner.getSelectedItemPosition() != AdapterView.INVALID_POSITION) {
-                mIgnoreNextDestinationChange = true;
-                mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
-            }
         }
 
         public boolean isCancelled() {
@@ -1054,11 +1271,7 @@
 
         public void confirmPrint() {
             mEditorState = EDITOR_STATE_CONFIRMED_PRINT;
-            PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
-            if (printer != null) {
-                mFavoritePrinters.addPrinter(printer);
-            }
-            updateUi();
+            showUi(UI_GENERATING_PRINT_JOB, null);
         }
 
         public boolean isPreviewConfirmed() {
@@ -1104,7 +1317,79 @@
             return ALL_PAGES_ARRAY;
         }
 
+        private void bindUi() {
+            if (mCurrentUi != UI_EDITING_PRINT_JOB) {
+                return;
+            }
+
+            // Content container
+            mContentContainer = findViewById(R.id.content_container);
+
+            // Copies
+            mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
+            mCopiesEditText.setText(MIN_COPIES_STRING);
+            mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
+            mCopiesEditText.selectAll();
+            if (!TextUtils.equals(mCopiesEditText.getText(), MIN_COPIES_STRING)) {
+                mIgnoreNextCopiesChange = true;
+            }
+            PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence(
+                    mPrintJobId, MIN_COPIES);
+
+            // Destination.
+            mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
+            mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
+            mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+            if (mDestinationSpinnerAdapter.getCount() > 0) {
+                mIgnoreNextDestinationChange = true;
+            }
+
+            // Media size.
+            mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
+            mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
+            mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+            if (mMediaSizeSpinnerAdapter.getCount() > 0) {
+                mIgnoreNextMediaSizeChange = true;
+            }
+
+            // Color mode.
+            mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
+            mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
+            mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+            if (mColorModeSpinnerAdapter.getCount() > 0) {
+                mIgnoreNextColorModeChange = true;
+            }
+
+            // Orientation
+            mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
+            mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
+            mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+            if (mOrientationSpinnerAdapter.getCount() > 0) {
+                mIgnoreNextOrientationChange = true;
+            }
+
+            // Range
+            mRangeTitle = (TextView) findViewById(R.id.page_range_title);
+            mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+            mRangeEditText.addTextChangedListener(mRangeTextWatcher);
+
+            // Range options
+            mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
+            mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
+            mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+            if (mRangeOptionsSpinnerAdapter.getCount() > 0) {
+                mIgnoreNextRangeOptionChange = true;
+            }
+
+            // Print button
+            mPrintButton = (Button) findViewById(R.id.print_button);
+            registerPrintButtonClickListener();
+        }
+
         public void updateUi() {
+            if (mCurrentUi != UI_EDITING_PRINT_JOB) {
+                return;
+            }
             if (isPrintConfirmed() || isPreviewConfirmed() || isCancelled()) {
                 mDestinationSpinner.setEnabled(false);
                 mCopiesEditText.setEnabled(false);
@@ -1119,14 +1404,20 @@
                 return;
             }
 
+            // If a printer with capabilities is selected, then we enabled all options.
+            boolean allOptionsEnabled = false;
             final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
+            if (selectedIndex >= 0) {
+                Object item = mDestinationSpinnerAdapter.getItem(selectedIndex);
+                if (item instanceof PrinterInfo) {
+                    PrinterInfo printer = (PrinterInfo) item;
+                    if (printer.getCapabilities() != null) {
+                        allOptionsEnabled = true;
+                    }
+                }
+            }
 
-            if (selectedIndex < 0 || ((PrinterInfo) mDestinationSpinnerAdapter.getItem(
-                    selectedIndex)).getCapabilities() == null) {
-
-                // Destination
-                mDestinationSpinner.setEnabled(false);
-
+            if (!allOptionsEnabled) {
                 String minCopiesString = String.valueOf(MIN_COPIES);
                 if (!TextUtils.equals(mCopiesEditText.getText(), minCopiesString)) {
                     mIgnoreNextCopiesChange = true;
@@ -1183,9 +1474,6 @@
                 PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
                 printer.getCapabilities().getDefaults(defaultAttributes);
 
-                // Destination
-                mDestinationSpinner.setEnabled(true);
-
                 // Copies
                 mCopiesEditText.setEnabled(true);
 
@@ -1223,6 +1511,7 @@
                         }
                     }
                 }
+                mMediaSizeSpinner.setEnabled(true);
 
                 // Color mode.
                 final int colorModes = capabilities.getColorModes();
@@ -1271,6 +1560,7 @@
                         }
                     }
                 }
+                mColorModeSpinner.setEnabled(true);
 
                 // Orientation.
                 final int orientations = capabilities.getOrientations();
@@ -1321,20 +1611,25 @@
                         }
                     }
                 }
+                mOrientationSpinner.setEnabled(true);
 
                 // Range options
                 PrintDocumentInfo info = mDocument.info;
                 if (info != null && (info.getPageCount() > 1
                         || info.getPageCount() == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) {
                     mRangeOptionsSpinner.setEnabled(true);
-                    if (mRangeOptionsSpinner.getSelectedItemPosition() > 0
-                            && !mRangeEditText.isEnabled()) {
-                        mRangeEditText.setEnabled(true);
-                        mRangeEditText.setVisibility(View.VISIBLE);
-                        mRangeEditText.requestFocus();
-                        InputMethodManager imm = (InputMethodManager)
-                                getSystemService(INPUT_METHOD_SERVICE);
-                        imm.showSoftInput(mRangeEditText, 0);
+                    if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
+                        if (!mRangeEditText.isEnabled()) {
+                            mRangeEditText.setEnabled(true);
+                            mRangeEditText.setVisibility(View.VISIBLE);
+                            mRangeEditText.requestFocus();
+                            InputMethodManager imm = (InputMethodManager)
+                                    getSystemService(INPUT_METHOD_SERVICE);
+                            imm.showSoftInput(mRangeEditText, 0);
+                        }
+                    } else {
+                        mRangeEditText.setEnabled(false);
+                        mRangeEditText.setVisibility(View.INVISIBLE);
                     }
                     final int pageCount = mDocument.info.getPageCount();
                     mRangeTitle.setText(getString(R.string.label_pages,
@@ -1352,6 +1647,7 @@
                     mRangeEditText.setEnabled(false);
                     mRangeEditText.setVisibility(View.INVISIBLE);
                 }
+                mRangeOptionsSpinner.setEnabled(true);
 
                 // Print/Print preview
                 if ((mRangeOptionsSpinner.getSelectedItemPosition() == 1
@@ -1378,6 +1674,7 @@
                     mCopiesEditText.selectAll();
                     mCopiesEditText.requestFocus();
                 }
+                mCopiesEditText.setEnabled(true);
             }
         }
 
@@ -1407,38 +1704,51 @@
             }
         }
 
-        private final class DestinationAdapter extends BaseAdapter {
-            private final AvailablePrinterProvider mProvider;
+        private final class DestinationAdapter extends BaseAdapter
+                implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>{
+            private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
 
-            private final DataSetObserver mObserver = new DataSetObserver() {
-                @Override
-                public void onChanged() {
-                    notifyDataSetChanged();
-                }
+            public final PrinterInfo mFakePdfPrinter;
 
-                @Override
-                public void onInvalidated() {
-                    notifyDataSetInvalidated();
-                }
-            };
-
-            public DestinationAdapter(AvailablePrinterProvider provider) {
-                mProvider = provider;
-                mProvider.registerObserver(mObserver);
+            public DestinationAdapter() {
+                getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
+                mFakePdfPrinter = createFakePdfPrinter();
             }
 
             @Override
             public int getCount() {
-                return mProvider.getItemCount();
+                return Math.max(Math.min(mPrinters.size(), DEST_ADAPTER_MAX_ITEM_COUNT),
+                        DEST_ADAPTER_MIN_ITEM_COUNT);
             }
 
             @Override
             public Object getItem(int position) {
-                return mProvider.getItemAt(position);
+                if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+                    return mFakePdfPrinter;
+                }
+                if (!mPrinters.isEmpty()) {
+                    if (position < DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+                        return mPrinters.get(position);
+                    } else if (position > DEST_ADAPTER_POSITION_SAVE_AS_PDF
+                            && position < getCount() - 1) {
+                        return mPrinters.get(position - 1);
+                    }
+                }
+                return null;
             }
 
             @Override
             public long getItemId(int position) {
+                if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+                    return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
+                }
+                if (mPrinters.isEmpty()) {
+                    if (position == DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS) {
+                        return DEST_ADAPTER_ITEM_ID_SEARCHING_FOR_PRINTERS;
+                    }
+                } else if (position == getCount() - 1) {
+                    return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
+                }
                 return position;
             }
 
@@ -1455,24 +1765,92 @@
                             R.layout.spinner_dropdown_item, parent, false);
                 }
 
-                PrinterInfo printerInfo = mProvider.getItemAt(position);
-                TextView title = (TextView) convertView.findViewById(R.id.title);
-                title.setText(printerInfo.getName());
+                CharSequence title = null;
+                CharSequence subtitle = null;
 
-                try {
-                    TextView subtitle = (TextView)
-                            convertView.findViewById(R.id.subtitle);
-                    PackageManager pm = getPackageManager();
-                    PackageInfo packageInfo = pm.getPackageInfo(
-                            printerInfo.getId().getServiceName().getPackageName(), 0);
-                    subtitle.setText(packageInfo.applicationInfo.loadLabel(pm));
-                    subtitle.setVisibility(View.VISIBLE);
-                } catch (NameNotFoundException nnfe) {
-                    /* ignore */
+                if (mPrinters.isEmpty()
+                        && position == DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS) {
+                        title = getString(R.string.searching_for_printers);
+                } else {
+                    if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+                        PrinterInfo printer = (PrinterInfo) getItem(position);
+                        title = printer.getName();
+                    } else if (position == getCount() - 1) {
+                        title = getString(R.string.all_printers);
+                    } else {
+                        PrinterInfo printer = (PrinterInfo) getItem(position);
+                        title = printer.getName();
+                        try {
+                            PackageInfo packageInfo = getPackageManager().getPackageInfo(
+                                    printer.getId().getServiceName().getPackageName(), 0);
+                            subtitle = packageInfo.applicationInfo.loadLabel(getPackageManager());
+                        } catch (NameNotFoundException nnfe) {
+                            /* ignore */
+                        }
+                    }
+                }
+
+                TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                titleView.setText(title);
+
+                TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle);
+                if (!TextUtils.isEmpty(subtitle)) {
+                    subtitleView.setText(subtitle);
+                    subtitleView.setVisibility(View.VISIBLE);
+                } else {
+                    subtitleView.setText(null);
+                    subtitleView.setVisibility(View.GONE);
                 }
 
                 return convertView;
             }
+
+            @Override
+            public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
+                if (id == LOADER_ID_PRINTERS_LOADER) {
+                    return new FusedPrintersProvider(PrintJobConfigActivity.this);
+                }
+                return null;
+            }
+
+            @Override
+            public void onLoadFinished(Loader<List<PrinterInfo>> loader,
+                    List<PrinterInfo> printers) {
+                mPrinters.clear();
+                mPrinters.addAll(printers);
+                notifyDataSetChanged();
+            }
+
+            @Override
+            public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
+                mPrinters.clear();
+                notifyDataSetInvalidated();
+            }
+
+            private PrinterInfo createFakePdfPrinter() {
+                PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
+
+                PrinterCapabilitiesInfo capabilities =
+                        new PrinterCapabilitiesInfo.Builder(printerId)
+                    .addMediaSize(MediaSize.createMediaSize(getPackageManager(),
+                            MediaSize.ISO_A4), true)
+                    .addMediaSize(MediaSize.createMediaSize(getPackageManager(),
+                            MediaSize.NA_LETTER), false)
+                    .addResolution(new Resolution("PDF resolution", "PDF resolution",
+                            300, 300), true)
+                    .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+                            | PrintAttributes.COLOR_MODE_MONOCHROME,
+                            PrintAttributes.COLOR_MODE_COLOR)
+                    .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
+                            | PrintAttributes.ORIENTATION_LANDSCAPE,
+                            PrintAttributes.ORIENTATION_PORTRAIT)
+                    .create();
+
+                return new PrinterInfo.Builder(printerId, getString(R.string.save_as_pdf),
+                        PrinterInfo.STATUS_READY)
+                    .setCapabilities(capabilities)
+                    .create();
+            }
         }
     }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
deleted file mode 100644
index c2cf65e..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
+++ /dev/null
@@ -1,969 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.ParcelFileDescriptor;
-import android.print.IPrintClient;
-import android.print.IPrinterDiscoverySessionObserver;
-import android.print.PageRange;
-import android.print.PrintAttributes;
-import android.print.PrintAttributes.Margins;
-import android.print.PrintAttributes.MediaSize;
-import android.print.PrintAttributes.Resolution;
-import android.print.PrintAttributes.Tray;
-import android.print.PrintDocumentInfo;
-import android.print.PrintJobInfo;
-import android.print.PrintManager;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
-import android.util.AtomicFile;
-import android.util.Log;
-import android.util.Slog;
-import android.util.Xml;
-
-import com.android.internal.util.FastXmlSerializer;
-
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class PrintSpooler {
-
-    private static final String LOG_TAG = "PrintSpooler";
-
-    private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = true;
-
-    private static final boolean DEBUG_PERSISTENCE = true;
-
-    private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
-
-    private static final String PRINT_FILE_EXTENSION = "pdf";
-
-    private static int sPrintJobIdCounter;
-
-    private static final Object sLock = new Object();
-
-    private static PrintSpooler sInstance;
-
-    private final Object mLock = new Object();
-
-    private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
-
-    private final PersistenceManager mPersistanceManager;
-
-    private final NotificationController mNotificationController;
-
-    private final PrintSpoolerService mService;
-
-    public static void destroyInstance() {
-        synchronized (sLock) {
-            sInstance = null;
-        }
-    }
-
-    public static void createInstance(PrintSpoolerService service) {
-        synchronized (sLock) {
-            sInstance = new PrintSpooler(service);
-        }
-    }
-
-    public static PrintSpooler peekInstance() {
-        synchronized (sLock) {
-            return sInstance;
-        }
-    }
-
-    private PrintSpooler(PrintSpoolerService service) {
-        mService = service;
-        mPersistanceManager = new PersistenceManager(service);
-        mNotificationController = new NotificationController(service);
-        synchronized (mLock) {
-            mPersistanceManager.readStateLocked();
-            handleReadPrintJobsLocked();
-        }
-    }
-
-    public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName,
-            int state, int appId) {
-        List<PrintJobInfo> foundPrintJobs = null;
-        synchronized (mLock) {
-            final int printJobCount = mPrintJobs.size();
-            for (int i = 0; i < printJobCount; i++) {
-                PrintJobInfo printJob = mPrintJobs.get(i);
-                PrinterId printerId = printJob.getPrinterId();
-                final boolean sameComponent = (componentName == null
-                        || (printerId != null
-                        && componentName.equals(printerId.getServiceName())));
-                final boolean sameAppId = appId == PrintManager.APP_ID_ANY
-                        || printJob.getAppId() == appId;
-                final boolean sameState = (state == printJob.getState())
-                        || (state == PrintJobInfo.STATE_ANY)
-                        || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS
-                                && printJob.getState() > PrintJobInfo.STATE_CREATED);
-                if (sameComponent && sameAppId && sameState) {
-                    if (foundPrintJobs == null) {
-                        foundPrintJobs = new ArrayList<PrintJobInfo>();
-                    }
-                    foundPrintJobs.add(printJob);
-                }
-            }
-        }
-        return foundPrintJobs;
-    }
-
-    public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
-        synchronized (mLock) {
-            final int printJobCount = mPrintJobs.size();
-            for (int i = 0; i < printJobCount; i++) {
-                PrintJobInfo printJob = mPrintJobs.get(i);
-                if (printJob.getId() == printJobId
-                        && (appId == PrintManager.APP_ID_ANY
-                                || appId == printJob.getAppId())) {
-                    return printJob;
-                }
-             }
-             return null;
-        }
-    }
-
-    public PrintJobInfo createPrintJob(CharSequence label, IPrintClient client,
-            PrintAttributes attributes, int appId) {
-        synchronized (mLock) {
-            final int printJobId = generatePrintJobIdLocked();
-            PrintJobInfo printJob = new PrintJobInfo();
-            printJob.setId(printJobId);
-            printJob.setAppId(appId);
-            printJob.setLabel(label);
-            printJob.setAttributes(attributes);
-            printJob.setState(PrintJobInfo.STATE_CREATED);
-
-            addPrintJobLocked(printJob);
-
-            return printJob;
-        }
-    }
-
-    private void handleReadPrintJobsLocked() {
-        final int printJobCount = mPrintJobs.size();
-        for (int i = 0; i < printJobCount; i++) {
-            PrintJobInfo printJob = mPrintJobs.get(i);
-
-            // Update the notification.
-            mNotificationController.onPrintJobStateChanged(printJob);
-
-            switch (printJob.getState()) {
-                case PrintJobInfo.STATE_QUEUED:
-                case PrintJobInfo.STATE_STARTED: {
-                    // We have a print job that was queued or started in the past
-                    // but the device battery died or a crash occurred. In this case
-                    // we assume the print job failed and let the user decide whether
-                    // to restart the job or just
-                    setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
-                            mService.getString(R.string.no_connection_to_printer));
-                } break;
-            }
-        }
-    }
-
-    public void checkAllPrintJobsHandled() {
-        synchronized (mLock) {
-            if (!hasActivePrintJobsLocked()) {
-                notifyOnAllPrintJobsHandled();
-            }
-        }
-    }
-
-    public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
-        mService.createPrinterDiscoverySession(observer);
-    }
-
-    private int generatePrintJobIdLocked() {
-        int printJobId = sPrintJobIdCounter++;
-        while (isDuplicatePrintJobId(printJobId)) {
-            printJobId = sPrintJobIdCounter++;
-        }
-        return printJobId;
-    }
-
-    private boolean isDuplicatePrintJobId(int printJobId) {
-        final int printJobCount = mPrintJobs.size();
-        for (int j = 0; j < printJobCount; j++) {
-            PrintJobInfo printJob = mPrintJobs.get(j);
-            if (printJob.getId() == printJobId) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void writePrintJobData(final ParcelFileDescriptor fd, final int printJobId) {
-        final PrintJobInfo printJob;
-        synchronized (mLock) {
-            printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-        }
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                FileInputStream in = null;
-                FileOutputStream out = null;
-                try {
-                    if (printJob != null) {
-                        File file = generateFileForPrintJob(printJobId);
-                        in = new FileInputStream(file);
-                        out = new FileOutputStream(fd.getFileDescriptor());
-                    }
-                    final byte[] buffer = new byte[8192];
-                    while (true) {
-                        final int readByteCount = in.read(buffer);
-                        if (readByteCount < 0) {
-                            return null;
-                        }
-                        out.write(buffer, 0, readByteCount);
-                    }
-                } catch (FileNotFoundException fnfe) {
-                    Log.e(LOG_TAG, "Error writing print job data!", fnfe);
-                } catch (IOException ioe) {
-                    Log.e(LOG_TAG, "Error writing print job data!", ioe);
-                } finally {
-                    IoUtils.closeQuietly(in);
-                    IoUtils.closeQuietly(out);
-                    IoUtils.closeQuietly(fd);
-                }
-                Log.i(LOG_TAG, "[END WRITE]");
-                return null;
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
-    }
-
-    public File generateFileForPrintJob(int printJobId) {
-        return new File(mService.getFilesDir(), "print_job_"
-                + printJobId + "." + PRINT_FILE_EXTENSION);
-    }
-
-    private void addPrintJobLocked(PrintJobInfo printJob) {
-        mPrintJobs.add(printJob);
-        if (DEBUG_PRINT_JOB_LIFECYCLE) {
-            Slog.i(LOG_TAG, "[ADD] " + printJob);
-        }
-    }
-
-    private void removePrintJobLocked(PrintJobInfo printJob) {
-        if (mPrintJobs.remove(printJob)) {
-            generateFileForPrintJob(printJob.getId()).delete();
-            if (DEBUG_PRINT_JOB_LIFECYCLE) {
-                Slog.i(LOG_TAG, "[REMOVE] " + printJob);
-            }
-        }
-    }
-
-    public boolean setPrintJobState(int printJobId, int state, CharSequence error) {
-        boolean success = false;
-
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                success = true;
-
-                printJob.setState(state);
-                printJob.setFailureReason(error);
-                mNotificationController.onPrintJobStateChanged(printJob);
-
-                if (DEBUG_PRINT_JOB_LIFECYCLE) {
-                    Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
-                }
-
-                switch (state) {
-                    case PrintJobInfo.STATE_COMPLETED:
-                    case PrintJobInfo.STATE_CANCELED:
-                        removePrintJobLocked(printJob);
-                        // $fall-through$
-                    case PrintJobInfo.STATE_FAILED: {
-                        PrinterId printerId = printJob.getPrinterId();
-                        if (printerId != null) {
-                            ComponentName service = printerId.getServiceName();
-                            if (!hasActivePrintJobsForServiceLocked(service)) {
-                                mService.onAllPrintJobsForServiceHandled(service);
-                            }
-                        }
-                    } break;
-
-                    case PrintJobInfo.STATE_QUEUED: {
-                        mService.onPrintJobQueued(new PrintJobInfo(printJob));
-                    } break;
-                }
-
-                if (shouldPersistPrintJob(printJob)) {
-                    mPersistanceManager.writeStateLocked();
-                }
-
-                if (!hasActivePrintJobsLocked()) {
-                    notifyOnAllPrintJobsHandled();
-                }
-            }
-        }
-
-        return success;
-    }
-
-    public boolean hasActivePrintJobsLocked() {
-        final int printJobCount = mPrintJobs.size();
-        for (int i = 0; i < printJobCount; i++) {
-            PrintJobInfo printJob = mPrintJobs.get(i);
-            if (isActiveState(printJob.getState())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean hasActivePrintJobsForServiceLocked(ComponentName service) {
-        final int printJobCount = mPrintJobs.size();
-        for (int i = 0; i < printJobCount; i++) {
-            PrintJobInfo printJob = mPrintJobs.get(i);
-            if (isActiveState(printJob.getState())
-                    && printJob.getPrinterId().getServiceName().equals(service)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static boolean isActiveState(int printJobState) {
-        return printJobState == PrintJobInfo.STATE_CREATED
-                || printJobState == PrintJobInfo.STATE_QUEUED
-                || printJobState == PrintJobInfo.STATE_STARTED;
-    }
-
-    public boolean setPrintJobTag(int printJobId, String tag) {
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                String printJobTag = printJob.getTag();
-                if (printJobTag == null) {
-                    if (tag == null) {
-                        return false;
-                    }
-                } else if (printJobTag.equals(tag)) {
-                    return false;
-                }
-                printJob.setTag(tag);
-                if (shouldPersistPrintJob(printJob)) {
-                    mPersistanceManager.writeStateLocked();
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void setPrintJobCopiesNoPersistence(int printJobId, int copies) {
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                printJob.setCopies(copies);
-            }
-        }
-    }
-
-    public void setPrintJobPrintDocumentInfoNoPersistence(int printJobId, PrintDocumentInfo info) {
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                printJob.setDocumentInfo(info);
-            }
-        }
-    }
-
-    public void setPrintJobAttributesNoPersistence(int printJobId, PrintAttributes attributes) {
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                printJob.setAttributes(attributes);
-            }
-        }
-    }
-
-    public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                printJob.setPrinterId(printer.getId());
-                printJob.setPrinterName(printer.getName());
-            }
-        }
-    }
-
-    public void setPrintJobPagesNoPersistence(int printJobId, PageRange[] pages) {
-        synchronized (mLock) {
-            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
-            if (printJob != null) {
-                printJob.setPages(pages);
-            }
-        }
-    }
-
-    private boolean shouldPersistPrintJob(PrintJobInfo printJob) {
-        return printJob.getState() >= PrintJobInfo.STATE_QUEUED;
-    }
-
-    private void notifyOnAllPrintJobsHandled() {
-        // This has to run on the tread that is persisting the current state
-        // since this call may result in the system unbinding from the spooler
-        // and as a result the spooler process may get killed before the write
-        // completes.
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                mService.onAllPrintJobsHandled();
-                return null;
-            }
-        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
-    }
-
-    private final class PersistenceManager {
-        private static final String PERSIST_FILE_NAME = "print_spooler_state.xml";
-
-        private static final String TAG_SPOOLER = "spooler";
-        private static final String TAG_JOB = "job";
-
-        private static final String TAG_PRINTER_ID = "printerId";
-        private static final String TAG_PAGE_RANGE = "pageRange";
-        private static final String TAG_ATTRIBUTES = "attributes";
-        private static final String TAG_DOCUMENT_INFO = "documentInfo";
-
-        private static final String ATTR_ID = "id";
-        private static final String ATTR_LABEL = "label";
-        private static final String ATTR_STATE = "state";
-        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_COPIES = "copies";
-
-        private static final String TAG_MEDIA_SIZE = "mediaSize";
-        private static final String TAG_RESOLUTION = "resolution";
-        private static final String TAG_MARGINS = "margins";
-        private static final String TAG_INPUT_TRAY = "inputTray";
-        private static final String TAG_OUTPUT_TRAY = "outputTray";
-
-        private static final String ATTR_DUPLEX_MODE = "duplexMode";
-        private static final String ATTR_COLOR_MODE = "colorMode";
-        private static final String ATTR_FITTING_MODE = "fittingMode";
-        private static final String ATTR_ORIENTATION = "orientation";
-
-        private static final String ATTR_LOCAL_ID = "printerName";
-        private static final String ATTR_SERVICE_NAME = "serviceName";
-
-        private static final String ATTR_WIDTH_MILS = "widthMils";
-        private static final String ATTR_HEIGHT_MILS = "heightMils";
-
-        private static final String ATTR_HORIZONTAL_DPI = "horizontalDip";
-        private static final String ATTR_VERTICAL_DPI = "verticalDpi";
-
-        private static final String ATTR_LEFT_MILS = "leftMils";
-        private static final String ATTR_TOP_MILS = "topMils";
-        private static final String ATTR_RIGHT_MILS = "rightMils";
-        private static final String ATTR_BOTTOM_MILS = "bottomMils";
-
-        private static final String ATTR_START = "start";
-        private static final String ATTR_END = "end";
-
-        private static final String ATTR_NAME = "name";
-        private static final String ATTR_PAGE_COUNT = "pageCount";
-        private static final String ATTR_CONTENT_TYPE = "contentType";
-
-        private final AtomicFile mStatePersistFile;
-
-        private boolean mWriteStateScheduled;
-
-        private PersistenceManager(Context context) {
-            mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
-                    PERSIST_FILE_NAME));
-        }
-
-        public void writeStateLocked() {
-            if (!PERSISTNECE_MANAGER_ENABLED) {
-                return;
-            }
-            if (mWriteStateScheduled) {
-                return;
-            }
-            mWriteStateScheduled = true;
-            new AsyncTask<Void, Void, Void>() {
-                @Override
-                protected Void doInBackground(Void... params) {
-                    synchronized (mLock) {
-                        mWriteStateScheduled = false;
-                        doWriteStateLocked();
-                    }
-                    return null;
-                }
-            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
-        }
-
-        private void doWriteStateLocked() {
-            if (DEBUG_PERSISTENCE) {
-                Log.i(LOG_TAG, "[PERSIST START]");
-            }
-            FileOutputStream out = null;
-            try {
-                out = mStatePersistFile.startWrite();
-
-                XmlSerializer serializer = new FastXmlSerializer();
-                serializer.setOutput(out, "utf-8");
-                serializer.startDocument(null, true);
-                serializer.startTag(null, TAG_SPOOLER);
-
-                List<PrintJobInfo> printJobs = mPrintJobs;
-
-                final int printJobCount = printJobs.size();
-                for (int j = 0; j < printJobCount; j++) {
-                    PrintJobInfo printJob = printJobs.get(j);
-
-                    final int state = printJob.getState();
-                    if (state < PrintJobInfo.STATE_QUEUED
-                            || state > PrintJobInfo.STATE_CANCELED) {
-                        continue;
-                    }
-
-                    serializer.startTag(null, TAG_JOB);
-
-                    serializer.attribute(null, ATTR_ID, String.valueOf(printJob.getId()));
-                    serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString());
-                    serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState()));
-                    serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId()));
-                    serializer.attribute(null, ATTR_USER_ID, String.valueOf(printJob.getUserId()));
-                    String tag = printJob.getTag();
-                    if (tag != null) {
-                        serializer.attribute(null, ATTR_TAG, tag);
-                    }
-                    serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies()));
-
-                    PrinterId printerId = printJob.getPrinterId();
-                    if (printerId != null) {
-                        serializer.startTag(null, TAG_PRINTER_ID);
-                        serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
-                        serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
-                                .flattenToString());
-                        serializer.endTag(null, TAG_PRINTER_ID);
-                    }
-
-                    PageRange[] pages = printJob.getPages();
-                    if (pages != null) {
-                        for (int i = 0; i < pages.length; i++) {
-                            serializer.startTag(null, TAG_PAGE_RANGE);
-                            serializer.attribute(null, ATTR_START, String.valueOf(
-                                    pages[i].getStart()));
-                            serializer.attribute(null, ATTR_END, String.valueOf(
-                                    pages[i].getEnd()));
-                            serializer.endTag(null, TAG_PAGE_RANGE);
-                        }
-                    }
-
-                    PrintAttributes attributes = printJob.getAttributes();
-                    if (attributes != null) {
-                        serializer.startTag(null, TAG_ATTRIBUTES);
-
-                        final int duplexMode = attributes.getDuplexMode();
-                        serializer.attribute(null, ATTR_DUPLEX_MODE,
-                                String.valueOf(duplexMode));
-
-                        final int colorMode = attributes.getColorMode();
-                        serializer.attribute(null, ATTR_COLOR_MODE,
-                                String.valueOf(colorMode));
-
-                        final int fittingMode = attributes.getFittingMode();
-                        serializer.attribute(null, ATTR_FITTING_MODE,
-                                String.valueOf(fittingMode));
-
-                        final int orientation = attributes.getOrientation();
-                        serializer.attribute(null, ATTR_ORIENTATION,
-                                String.valueOf(orientation));
-
-                        MediaSize mediaSize = attributes.getMediaSize();
-                        if (mediaSize != null) {
-                            serializer.startTag(null, TAG_MEDIA_SIZE);
-                            serializer.attribute(null, ATTR_ID, mediaSize.getId());
-                            serializer.attribute(null, ATTR_LABEL, mediaSize.getLabel()
-                                    .toString());
-                            serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf(
-                                    mediaSize.getWidthMils()));
-                            serializer.attribute(null, ATTR_HEIGHT_MILS,String.valueOf(
-                                    mediaSize.getHeightMils()));
-                            serializer.endTag(null, TAG_MEDIA_SIZE);
-                        }
-
-                        Resolution resolution = attributes.getResolution();
-                        if (resolution != null) {
-                            serializer.startTag(null, TAG_RESOLUTION);
-                            serializer.attribute(null, ATTR_ID, resolution.getId());
-                            serializer.attribute(null, ATTR_LABEL, resolution.getLabel()
-                                    .toString());
-                            serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf(
-                                     resolution.getHorizontalDpi()));
-                            serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
-                                    resolution.getVerticalDpi()));
-                            serializer.endTag(null, TAG_RESOLUTION);
-                        }
-
-                        Margins margins = attributes.getMargins();
-                        if (margins != null) {
-                            serializer.startTag(null, TAG_MARGINS);
-                            serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf(
-                                    margins.getLeftMils()));
-                            serializer.attribute(null, ATTR_TOP_MILS, String.valueOf(
-                                    margins.getTopMils()));
-                            serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf(
-                                    margins.getRightMils()));
-                            serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf(
-                                    margins.getBottomMils()));
-                            serializer.endTag(null, TAG_MARGINS);
-                        }
-
-                        Tray inputTray = attributes.getInputTray();
-                        if (inputTray != null) {
-                            serializer.startTag(null, TAG_INPUT_TRAY);
-                            serializer.attribute(null, ATTR_ID, inputTray.getId());
-                            serializer.attribute(null, ATTR_LABEL, inputTray.getLabel()
-                                    .toString());
-                            serializer.endTag(null, TAG_INPUT_TRAY);
-                        }
-
-                        Tray outputTray = attributes.getOutputTray();
-                        if (outputTray != null) {
-                            serializer.startTag(null, TAG_OUTPUT_TRAY);
-                            serializer.attribute(null, ATTR_ID, outputTray.getId());
-                            serializer.attribute(null, ATTR_LABEL, outputTray.getLabel()
-                                    .toString());
-                            serializer.endTag(null, TAG_OUTPUT_TRAY);
-                        }
-
-                        serializer.endTag(null, TAG_ATTRIBUTES);
-                    }
-
-                    PrintDocumentInfo documentInfo = printJob.getDocumentInfo();
-                    if (documentInfo != null) {
-                        serializer.startTag(null, TAG_DOCUMENT_INFO);
-                        serializer.attribute(null, ATTR_NAME, documentInfo.getName());
-                        serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf(
-                                documentInfo.getContentType()));
-                        serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf(
-                                documentInfo.getPageCount()));
-                        serializer.endTag(null, TAG_DOCUMENT_INFO);
-                    }
-
-                    serializer.endTag(null, TAG_JOB);
-
-                    if (DEBUG_PERSISTENCE) {
-                        Log.i(LOG_TAG, "[PERSISTED] " + printJob);
-                    }
-                }
-
-                serializer.endTag(null, TAG_SPOOLER);
-                serializer.endDocument();
-                mStatePersistFile.finishWrite(out);
-                if (DEBUG_PERSISTENCE) {
-                    Log.i(LOG_TAG, "[PERSIST END]");
-                }
-            } catch (IOException e) {
-                Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
-                mStatePersistFile.failWrite(out);
-            } finally {
-                IoUtils.closeQuietly(out);
-            }
-        }
-
-        public void readStateLocked() {
-            if (!PERSISTNECE_MANAGER_ENABLED) {
-                return;
-            }
-            FileInputStream in = null;
-            try {
-                in = mStatePersistFile.openRead();
-            } catch (FileNotFoundException e) {
-                Log.i(LOG_TAG, "No existing print spooler state.");
-                return;
-            }
-            try {
-                XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(in, null);
-                parseState(parser);
-            } catch (IllegalStateException ise) {
-                Slog.w(LOG_TAG, "Failed parsing ", ise);
-            } catch (NullPointerException npe) {
-                Slog.w(LOG_TAG, "Failed parsing ", npe);
-            } catch (NumberFormatException nfe) {
-                Slog.w(LOG_TAG, "Failed parsing ", nfe);
-            } catch (XmlPullParserException xppe) {
-                Slog.w(LOG_TAG, "Failed parsing ", xppe);
-            } catch (IOException ioe) {
-                Slog.w(LOG_TAG, "Failed parsing ", ioe);
-            } catch (IndexOutOfBoundsException iobe) {
-                Slog.w(LOG_TAG, "Failed parsing ", iobe);
-            } finally {
-                IoUtils.closeQuietly(in);
-            }
-        }
-
-        private void parseState(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            parser.next();
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
-            parser.next();
-
-            while (parsePrintJob(parser)) {
-                parser.next();
-            }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
-        }
-
-        private boolean parsePrintJob(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            skipEmptyTextTags(parser);
-            if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
-                return false;
-            }
-
-            PrintJobInfo printJob = new PrintJobInfo();
-
-            final int printJobId = Integer.parseInt(parser.getAttributeValue(null, ATTR_ID));
-            printJob.setId(printJobId);
-            String label = parser.getAttributeValue(null, ATTR_LABEL);
-            printJob.setLabel(label);
-            final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE));
-            printJob.setState(state);
-            final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID));
-            printJob.setAppId(appId);
-            final int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USER_ID));
-            printJob.setUserId(userId);
-            String tag = parser.getAttributeValue(null, ATTR_TAG);
-            printJob.setTag(tag);
-            String copies = parser.getAttributeValue(null, ATTR_COPIES);
-            printJob.setCopies(Integer.parseInt(copies));
-
-            parser.next();
-
-            skipEmptyTextTags(parser);
-            if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
-                String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
-                ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
-                        null, ATTR_SERVICE_NAME));
-                printJob.setPrinterId(new PrinterId(service, localId));
-                parser.next();
-                skipEmptyTextTags(parser);
-                expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
-                parser.next();
-            }
-
-            skipEmptyTextTags(parser);
-            List<PageRange> pageRanges = null;
-            while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) {
-                final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START));
-                final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END));
-                PageRange pageRange = new PageRange(start, end);
-                if (pageRanges == null) {
-                    pageRanges = new ArrayList<PageRange>();
-                }
-                pageRanges.add(pageRange);
-                parser.next();
-                skipEmptyTextTags(parser);
-                expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE);
-                parser.next();
-            }
-            if (pageRanges != null) {
-                PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
-                pageRanges.toArray(pageRangesArray);
-                printJob.setPages(pageRangesArray);
-            }
-
-            skipEmptyTextTags(parser);
-            if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) {
-
-                PrintAttributes.Builder builder = new PrintAttributes.Builder();
-
-                String duplexMode = parser.getAttributeValue(null, ATTR_DUPLEX_MODE);
-                builder.setDuplexMode(Integer.parseInt(duplexMode));
-
-                String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
-                builder.setColorMode(Integer.parseInt(colorMode));
-
-                String fittingMode = parser.getAttributeValue(null, ATTR_FITTING_MODE);
-                builder.setFittingMode(Integer.parseInt(fittingMode));
-
-                String orientation = parser.getAttributeValue(null, ATTR_ORIENTATION);
-                builder.setOrientation(Integer.parseInt(orientation));
-
-                parser.next();
-
-                skipEmptyTextTags(parser);
-                if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) {
-                    String id = parser.getAttributeValue(null, ATTR_ID);
-                    label = parser.getAttributeValue(null, ATTR_LABEL);
-                    final int widthMils = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_WIDTH_MILS));
-                    final int heightMils = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_HEIGHT_MILS));
-                    MediaSize mediaSize = new MediaSize(id, label, widthMils, heightMils);
-                    builder.setMediaSize(mediaSize);
-                    parser.next();
-                    skipEmptyTextTags(parser);
-                    expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE);
-                    parser.next();
-                }
-
-                skipEmptyTextTags(parser);
-                if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) {
-                    String id = parser.getAttributeValue(null, ATTR_ID);
-                    label = parser.getAttributeValue(null, ATTR_LABEL);
-                    final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_HORIZONTAL_DPI));
-                    final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_VERTICAL_DPI));
-                    Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
-                    builder.setResolution(resolution);
-                    parser.next();
-                    skipEmptyTextTags(parser);
-                    expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION);
-                    parser.next();
-                }
-
-                skipEmptyTextTags(parser);
-                if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) {
-                    final int leftMils = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_LEFT_MILS));
-                    final int topMils = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_TOP_MILS));
-                    final int rightMils = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_RIGHT_MILS));
-                    final int bottomMils = Integer.parseInt(parser.getAttributeValue(null,
-                            ATTR_BOTTOM_MILS));
-                    Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils);
-                    builder.setMargins(margins);
-                    parser.next();
-                    skipEmptyTextTags(parser);
-                    expect(parser, XmlPullParser.END_TAG, TAG_MARGINS);
-                    parser.next();
-                }
-
-                skipEmptyTextTags(parser);
-                if (accept(parser, XmlPullParser.START_TAG, TAG_INPUT_TRAY)) {
-                    String id = parser.getAttributeValue(null, ATTR_ID);
-                    label = parser.getAttributeValue(null, ATTR_LABEL);
-                    Tray tray = new Tray(id, label);
-                    builder.setInputTray(tray);
-                    parser.next();
-                    skipEmptyTextTags(parser);
-                    expect(parser, XmlPullParser.END_TAG, TAG_INPUT_TRAY);
-                    parser.next();
-                }
-
-                skipEmptyTextTags(parser);
-                if (accept(parser, XmlPullParser.START_TAG, TAG_OUTPUT_TRAY)) {
-                    String id = parser.getAttributeValue(null, ATTR_ID);
-                    label = parser.getAttributeValue(null, ATTR_LABEL);
-                    Tray tray = new Tray(id, label);
-                    builder.setOutputTray(tray);
-                    parser.next();
-                    skipEmptyTextTags(parser);
-                    expect(parser, XmlPullParser.END_TAG, TAG_OUTPUT_TRAY);
-                    parser.next();
-                }
-
-                printJob.setAttributes(builder.create());
-
-                skipEmptyTextTags(parser);
-                expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
-                parser.next();
-            }
-
-            skipEmptyTextTags(parser);
-            if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
-                String name = parser.getAttributeValue(null, ATTR_NAME);
-                final int pageCount = Integer.parseInt(parser.getAttributeValue(null,
-                        ATTR_PAGE_COUNT));
-                final int contentType = Integer.parseInt(parser.getAttributeValue(null,
-                        ATTR_CONTENT_TYPE));
-                PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
-                        .setPageCount(pageCount)
-                        .setContentType(contentType).create();
-                printJob.setDocumentInfo(info);
-                parser.next();
-                skipEmptyTextTags(parser);
-                expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO);
-                parser.next();
-            }
-
-            mPrintJobs.add(printJob);
-
-            if (DEBUG_PERSISTENCE) {
-                Log.i(LOG_TAG, "[RESTORED] " + printJob);
-            }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_JOB);
-
-            return true;
-        }
-
-        private void expect(XmlPullParser parser, int type, String tag)
-                throws IOException, XmlPullParserException {
-            if (!accept(parser, type, tag)) {
-                throw new XmlPullParserException("Exepected event: " + type
-                        + " and tag: " + tag + " but got event: " + parser.getEventType()
-                        + " and tag:" + parser.getName());
-            }
-        }
-
-        private void skipEmptyTextTags(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            while (accept(parser, XmlPullParser.TEXT, null)
-                    && "\n".equals(parser.getText())) {
-                parser.next();
-            }
-        }
-
-        private boolean accept(XmlPullParser parser, int type, String tag)
-                throws IOException, XmlPullParserException {
-            if (parser.getEventType() != type) {
-                return false;
-            }
-            if (tag != null) {
-                if (!tag.equals(parser.getName())) {
-                    return false;
-                }
-            } else if (parser.getName() != null) {
-                return false;
-            }
-            return true;
-        }
-    }
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index 4fab4f8..fda64c9 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -21,9 +21,8 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentSender;
-import android.os.Handler;
+import android.os.AsyncTask;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -32,14 +31,38 @@
 import android.print.IPrintSpooler;
 import android.print.IPrintSpoolerCallbacks;
 import android.print.IPrintSpoolerClient;
-import android.print.IPrinterDiscoverySessionObserver;
+import android.print.PageRange;
 import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintAttributes.Tray;
+import android.print.PrintDocumentInfo;
 import android.print.PrintJobInfo;
+import android.print.PrintManager;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
+import android.util.Xml;
 
+import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.util.FastXmlSerializer;
 
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -48,22 +71,65 @@
  */
 public final class PrintSpoolerService extends Service {
 
+    private static final String LOG_TAG = "PrintSpoolerService";
+
+    private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = true;
+
+    private static final boolean DEBUG_PERSISTENCE = true;
+
+    private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
+
     private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;
 
-    private static final String LOG_TAG = "PrintSpoolerService";
+    private static final String PRINT_FILE_EXTENSION = "pdf";
+
+    private static final Object sLock = new Object();
+
+    private final Object mLock = new Object();
+
+    private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
+
+    private static PrintSpoolerService sInstance;
+
+    private static int sPrintJobIdCounter;
 
     private Intent mStartPrintJobConfigActivityIntent;
 
     private IPrintSpoolerClient mClient;
 
-    private Handler mHandler;
+    private HandlerCaller mHandlerCaller;
+
+    private PersistenceManager mPersistanceManager;
+
+    private NotificationController mNotificationController;
+
+    private PrinterDiscoverySession mDiscoverySession;
+
+    public static PrintSpoolerService peekInstance() {
+        synchronized (sLock) {
+            return sInstance;
+        }
+    }
 
     @Override
     public void onCreate() {
         super.onCreate();
         mStartPrintJobConfigActivityIntent = new Intent(PrintSpoolerService.this,
                 PrintJobConfigActivity.class);
-        mHandler = new MyHandler(getMainLooper());
+        mHandlerCaller = new HandlerCaller(this, getMainLooper(),
+                new HandlerCallerCallback(), false);
+
+        mPersistanceManager = new PersistenceManager();
+        mNotificationController = new NotificationController(PrintSpoolerService.this);
+
+        synchronized (mLock) {
+            mPersistanceManager.readStateLocked();
+            handleReadPrintJobsLocked();
+        }
+
+        synchronized (sLock) {
+            sInstance = this;
+        }
     }
 
     @Override
@@ -72,10 +138,10 @@
             @Override
             public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
                     ComponentName componentName, int state, int appId, int sequence)
-                            throws RemoteException {
+                    throws RemoteException {
                 List<PrintJobInfo> printJobs = null;
                 try {
-                    printJobs = PrintSpooler.peekInstance().getPrintJobInfos(
+                    printJobs = PrintSpoolerService.this.getPrintJobInfos(
                             componentName, state, appId);
                 } finally {
                     callback.onGetPrintJobInfosResult(printJobs, sequence);
@@ -87,7 +153,7 @@
                     int appId, int sequence) throws RemoteException {
                 PrintJobInfo printJob = null;
                 try {
-                    printJob = PrintSpooler.peekInstance().getPrintJobInfo(printJobId, appId);
+                    printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId);
                 } finally {
                     callback.onGetPrintJobInfoResult(printJob, sequence);
                 }
@@ -98,11 +164,11 @@
             public void createPrintJob(String printJobName, IPrintClient client,
                     IPrintDocumentAdapter printAdapter, PrintAttributes attributes,
                     IPrintSpoolerCallbacks callback, int appId, int sequence)
-                            throws RemoteException {
+                    throws RemoteException {
                 PrintJobInfo printJob = null;
                 try {
-                    printJob = PrintSpooler.peekInstance().createPrintJob(printJobName, client,
-                            attributes, appId);
+                    printJob = PrintSpoolerService.this.createPrintJob(
+                            printJobName, client, attributes, appId);
                     if (printJob != null) {
                         Intent intent = mStartPrintJobConfigActivityIntent;
                         intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
@@ -113,13 +179,12 @@
 
                         IntentSender sender = PendingIntent.getActivity(
                                 PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
-                                | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
+                                        | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
 
-                        SomeArgs args = SomeArgs.obtain();
-                        args.arg1 = client;
-                        args.arg2 = sender;
-                        mHandler.obtainMessage(MyHandler.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
-                                args).sendToTarget();
+                        Message message = mHandlerCaller.obtainMessageOO(
+                                HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
+                                client, sender);
+                        mHandlerCaller.executeOrSendMessage(message);
                     }
                 } finally {
                     callback.onCreatePrintJobResult(printJob, sequence);
@@ -127,11 +192,11 @@
             }
 
             @Override
-            public void setPrintJobState(int printJobId, int state, CharSequence error,
+            public void setPrintJobState(int printJobId, int state, String error,
                     IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
                 boolean success = false;
                 try {
-                    success = PrintSpooler.peekInstance().setPrintJobState(
+                    success = PrintSpoolerService.this.setPrintJobState(
                             printJobId, state, error);
                 } finally {
                     callback.onSetPrintJobStateResult(success, sequece);
@@ -143,7 +208,7 @@
                     IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
                 boolean success = false;
                 try {
-                    success = PrintSpooler.peekInstance().setPrintJobTag(printJobId, tag);
+                    success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag);
                 } finally {
                     callback.onSetPrintJobTagResult(success, sequece);
                 }
@@ -151,60 +216,191 @@
 
             @Override
             public void writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
-                PrintSpooler.peekInstance().writePrintJobData(fd, printJobId);
+                PrintSpoolerService.this.writePrintJobData(fd, printJobId);
             }
 
             @Override
             public void setClient(IPrintSpoolerClient client) {
-                mHandler.obtainMessage(MyHandler.MSG_SET_CLIENT, client).sendToTarget();
+                Message message = mHandlerCaller.obtainMessageO(
+                        HandlerCallerCallback.MSG_SET_CLIENT, client);
+                mHandlerCaller.executeOrSendMessage(message);
+            }
+
+            @Override
+            public void onPrintersAdded(List<PrinterInfo> printers) {
+                Message message = mHandlerCaller.obtainMessageO(
+                        HandlerCallerCallback.MSG_ON_PRINTERS_ADDED, printers);
+                mHandlerCaller.executeOrSendMessage(message);
+            }
+
+            @Override
+            public void onPrintersRemoved(List<PrinterId> printerIds) {
+                Message message = mHandlerCaller.obtainMessageO(
+                        HandlerCallerCallback.MSG_ON_PRINTERS_REMOVED, printerIds);
+                mHandlerCaller.executeOrSendMessage(message);
+            }
+
+            @Override
+            public void onPrintersUpdated(List<PrinterInfo> printers) {
+                Message message = mHandlerCaller.obtainMessageO(
+                        HandlerCallerCallback.MSG_ON_PRINTERS_UPDATED, printers);
+                mHandlerCaller.executeOrSendMessage(message);
             }
         };
     }
 
-    public void onPrintJobQueued(PrintJobInfo printJob) {
-        mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED,
-                printJob).sendToTarget();
+    public void createPrinterDiscoverySession() {
+        Message message = mHandlerCaller.obtainMessage(
+                HandlerCallerCallback.MSG_CREATE_PRINTER_DISCOVERY_SESSION);
+        mHandlerCaller.executeOrSendMessage(message);
     }
 
-    public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
-        mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
-                observer).sendToTarget();
+    public void destroyPrinterDiscoverySession() {
+        Message message = mHandlerCaller.obtainMessage(
+                HandlerCallerCallback.MSG_DESTROY_PRINTER_DISCOVERY_SESSION);
+        mHandlerCaller.executeOrSendMessage(message);
     }
 
-    public void onAllPrintJobsForServiceHandled(ComponentName service) {
-        mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
-                service).sendToTarget();
+    public void startPrinterDiscovery(List<PrinterId> priorityList) {
+        Message message = mHandlerCaller.obtainMessageO(
+                HandlerCallerCallback.MSG_START_PRINTER_DISCOVERY, priorityList);
+        mHandlerCaller.executeOrSendMessage(message);
     }
 
-    public void onAllPrintJobsHandled() {
-        mHandler.sendEmptyMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED);
+    public void stopPrinterDiscovery() {
+        Message message = mHandlerCaller.obtainMessage(
+                HandlerCallerCallback.MSG_STOP_PRINTER_DISCOVERY);
+        mHandlerCaller.executeOrSendMessage(message);
     }
 
-    private final class MyHandler extends Handler {
-        public static final int MSG_SET_CLIENT = 1;
-        public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2;
-        public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 3;
-        public static final int MSG_ON_PRINT_JOB_QUEUED = 5;
-        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 6;
-        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 7;
-        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 9;
+    public void requestPrinterUpdate(PrinterId pritnerId) {
+        Message message = mHandlerCaller.obtainMessageO(
+                HandlerCallerCallback.MSG_REQUEST_PRINTER_UPDATE, pritnerId);
+        mHandlerCaller.executeOrSendMessage(message);
+    }
 
-        public MyHandler(Looper looper) {
-            super(looper, null, false);
-        }
+
+    private void sendOnPrintJobQueued(PrintJobInfo printJob) {
+        Message message = mHandlerCaller.obtainMessageO(
+                HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob);
+        mHandlerCaller.executeOrSendMessage(message);
+    }
+
+    private void sendOnAllPrintJobsForServiceHandled(ComponentName service) {
+        Message message = mHandlerCaller.obtainMessageO(
+                HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, service);
+        mHandlerCaller.executeOrSendMessage(message);
+    }
+
+    private void sendOnAllPrintJobsHandled() {
+        Message message = mHandlerCaller.obtainMessage(
+                HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_HANDLED);
+        mHandlerCaller.executeOrSendMessage(message);
+    }
+
+    private final class HandlerCallerCallback implements HandlerCaller.Callback {
+        public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1;
+        public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
+        public static final int MSG_START_PRINTER_DISCOVERY = 3;
+        public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
+        public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
+
+        public static final int MSG_ON_PRINTERS_ADDED = 6;
+        public static final int MSG_ON_PRINTERS_REMOVED = 7;
+        public static final int MSG_ON_PRINTERS_UPDATED = 8;
+
+        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;
 
         @Override
-        public void handleMessage(Message message) {
+        @SuppressWarnings("unchecked")
+        public void executeMessage(Message message) {
             switch (message.what) {
+                case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+                    final IPrintSpoolerClient client;
+                    synchronized (mLock) {
+                        client = mClient;
+                    }
+                    if (client != null) {
+                        try {
+                            client.createPrinterDiscoverySession();
+                        } catch (RemoteException re) {
+                            Log.e(LOG_TAG, "Error creating printer discovery session.", re);
+                        }
+                    }
+                } break;
+
+                case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
+                    final IPrintSpoolerClient client;
+                    synchronized (mLock) {
+                        client = mClient;
+                    }
+                    if (client != null) {
+                        try {
+                            client.destroyPrinterDiscoverySession();
+                        } catch (RemoteException re) {
+                            Log.e(LOG_TAG, "Error destroying printer discovery session.", re);
+                        }
+                    }
+                } break;
+
+                case MSG_START_PRINTER_DISCOVERY: {
+                    final IPrintSpoolerClient client;
+                    synchronized (mLock) {
+                        client = mClient;
+                    }
+                    if (client != null) {
+                        List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj;
+                        try {
+                            client.startPrinterDiscovery(priorityList);
+                        } catch (RemoteException re) {
+                            Log.e(LOG_TAG, "Error starting printer discovery.", re);
+                        }
+                    }
+                } break;
+
+                case MSG_STOP_PRINTER_DISCOVERY: {
+                    final IPrintSpoolerClient client;
+                    synchronized (mLock) {
+                        client = mClient;
+                    }
+                    if (client != null) {
+                        try {
+                            client.stopPrinterDiscovery();
+                        } catch (RemoteException re) {
+                            Log.e(LOG_TAG, "Error stopping printer discovery.", re);
+                        }
+                    }
+                } break;
+
+                case MSG_REQUEST_PRINTER_UPDATE: {
+                    final IPrintSpoolerClient client;
+                    synchronized (mLock) {
+                        client = mClient;
+                    }
+                    if (client != null) {
+                        PrinterId printerId = (PrinterId) message.obj;
+                        try {
+                            client.requestPrinterUpdate(printerId);
+                        } catch (RemoteException re) {
+                            Log.e(LOG_TAG, "Error requesing printer update.", re);
+                        }
+                    }
+                } break;
+
                 case MSG_SET_CLIENT: {
-                    mClient = (IPrintSpoolerClient) message.obj;
-                    if (mClient != null) {
-                        PrintSpooler.createInstance(PrintSpoolerService.this);
-                        mHandler.sendEmptyMessageDelayed(
-                                MyHandler.MSG_CHECK_ALL_PRINTJOBS_HANDLED,
-                                CHECK_ALL_PRINTJOBS_HANDLED_DELAY);
-                    } else {
-                        PrintSpooler.destroyInstance();
+                    synchronized (mLock) {
+                        mClient = (IPrintSpoolerClient) message.obj;
+                        if (mClient != null) {
+                            Message msg = mHandlerCaller.obtainMessage(
+                                    HandlerCallerCallback.MSG_CHECK_ALL_PRINTJOBS_HANDLED);
+                            mHandlerCaller.sendMessageDelayed(msg,
+                                    CHECK_ALL_PRINTJOBS_HANDLED_DELAY);
+                        }
                     }
                 } break;
 
@@ -220,18 +416,6 @@
                     }
                 } break;
 
-                case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
-                    IPrinterDiscoverySessionObserver observer =
-                            (IPrinterDiscoverySessionObserver) message.obj;
-                    if (mClient != null) {
-                        try {
-                            mClient.createPrinterDiscoverySession(observer);
-                        } catch (RemoteException re) {
-                            Log.e(LOG_TAG, "Error creating printer discovery session.", re);
-                        }
-                    }
-                } break;
-
                 case MSG_ON_PRINT_JOB_QUEUED: {
                     PrintJobInfo printJob = (PrintJobInfo) message.obj;
                     if (mClient != null) {
@@ -266,12 +450,948 @@
                 } break;
 
                 case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
-                    PrintSpooler spooler = PrintSpooler.peekInstance();
-                    if (spooler != null) {
-                        spooler.checkAllPrintJobsHandled();
+                    checkAllPrintJobsHandled();
+                } break;
+
+                case MSG_ON_PRINTERS_ADDED: {
+                    final PrinterDiscoverySession session;
+                    synchronized (mLock) {
+                        session = mDiscoverySession;
+                    }
+                    if (session != null) {
+                        List<PrinterInfo> printers = (ArrayList<PrinterInfo>) message.obj;
+                        session.onPrintersAdded(printers);
+                    }
+                } break;
+
+                case MSG_ON_PRINTERS_REMOVED: {
+                    final PrinterDiscoverySession session;
+                    synchronized (mLock) {
+                        session = mDiscoverySession;
+                    }
+                    if (session != null) {
+                        List<PrinterId> printerIds = (ArrayList<PrinterId>) message.obj;
+                        session.onPrintersRemoved(printerIds);
+                    }
+                } break;
+
+                case MSG_ON_PRINTERS_UPDATED: {
+                    final PrinterDiscoverySession session;
+                    synchronized (mLock) {
+                        session = mDiscoverySession;
+                    }
+                    if (session != null) {
+                        List<PrinterInfo> printers = (ArrayList<PrinterInfo>) message.obj;
+                        session.onPrintersUpdated(printers);
                     }
                 } break;
             }
         }
     }
+
+    public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName,
+            int state, int appId) {
+        List<PrintJobInfo> foundPrintJobs = null;
+        synchronized (mLock) {
+            final int printJobCount = mPrintJobs.size();
+            for (int i = 0; i < printJobCount; i++) {
+                PrintJobInfo printJob = mPrintJobs.get(i);
+                PrinterId printerId = printJob.getPrinterId();
+                final boolean sameComponent = (componentName == null
+                        || (printerId != null
+                        && componentName.equals(printerId.getServiceName())));
+                final boolean sameAppId = appId == PrintManager.APP_ID_ANY
+                        || printJob.getAppId() == appId;
+                final boolean sameState = (state == printJob.getState())
+                        || (state == PrintJobInfo.STATE_ANY)
+                        || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS
+                        && printJob.getState() > PrintJobInfo.STATE_CREATED);
+                if (sameComponent && sameAppId && sameState) {
+                    if (foundPrintJobs == null) {
+                        foundPrintJobs = new ArrayList<PrintJobInfo>();
+                    }
+                    foundPrintJobs.add(printJob);
+                }
+            }
+        }
+        return foundPrintJobs;
+    }
+
+    public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
+        synchronized (mLock) {
+            final int printJobCount = mPrintJobs.size();
+            for (int i = 0; i < printJobCount; i++) {
+                PrintJobInfo printJob = mPrintJobs.get(i);
+                if (printJob.getId() == printJobId
+                        && (appId == PrintManager.APP_ID_ANY
+                        || appId == printJob.getAppId())) {
+                    return printJob;
+                }
+            }
+            return null;
+        }
+    }
+
+    public PrintJobInfo createPrintJob(String label, IPrintClient client,
+            PrintAttributes attributes, int appId) {
+        synchronized (mLock) {
+            final int printJobId = generatePrintJobIdLocked();
+            PrintJobInfo printJob = new PrintJobInfo();
+            printJob.setId(printJobId);
+            printJob.setAppId(appId);
+            printJob.setLabel(label);
+            printJob.setAttributes(attributes);
+            printJob.setState(PrintJobInfo.STATE_CREATED);
+
+            addPrintJobLocked(printJob);
+
+            return printJob;
+        }
+    }
+
+    private void handleReadPrintJobsLocked() {
+        final int printJobCount = mPrintJobs.size();
+        for (int i = 0; i < printJobCount; i++) {
+            PrintJobInfo printJob = mPrintJobs.get(i);
+
+            // Update the notification.
+            mNotificationController.onPrintJobStateChanged(printJob);
+
+            switch (printJob.getState()) {
+                case PrintJobInfo.STATE_QUEUED:
+                case PrintJobInfo.STATE_STARTED: {
+                    // We have a print job that was queued or started in the
+                    // past
+                    // but the device battery died or a crash occurred. In this
+                    // case
+                    // we assume the print job failed and let the user decide
+                    // whether
+                    // to restart the job or just
+                    setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
+                            getString(R.string.no_connection_to_printer));
+                }
+                    break;
+            }
+        }
+    }
+
+    public void checkAllPrintJobsHandled() {
+        synchronized (mLock) {
+            if (!hasActivePrintJobsLocked()) {
+                notifyOnAllPrintJobsHandled();
+            }
+        }
+    }
+
+    private void setPrinterDiscoverySessionClient(PrinterDiscoverySession session) {
+        synchronized (mLock) {
+            mDiscoverySession = session;
+        }
+    }
+
+    private int generatePrintJobIdLocked() {
+        int printJobId = sPrintJobIdCounter++;
+        while (isDuplicatePrintJobId(printJobId)) {
+            printJobId = sPrintJobIdCounter++;
+        }
+        return printJobId;
+    }
+
+    private boolean isDuplicatePrintJobId(int printJobId) {
+        final int printJobCount = mPrintJobs.size();
+        for (int j = 0; j < printJobCount; j++) {
+            PrintJobInfo printJob = mPrintJobs.get(j);
+            if (printJob.getId() == printJobId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void writePrintJobData(final ParcelFileDescriptor fd, final int printJobId) {
+        final PrintJobInfo printJob;
+        synchronized (mLock) {
+            printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+        }
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                FileInputStream in = null;
+                FileOutputStream out = null;
+                try {
+                    if (printJob != null) {
+                        File file = generateFileForPrintJob(printJobId);
+                        in = new FileInputStream(file);
+                        out = new FileOutputStream(fd.getFileDescriptor());
+                    }
+                    final byte[] buffer = new byte[8192];
+                    while (true) {
+                        final int readByteCount = in.read(buffer);
+                        if (readByteCount < 0) {
+                            return null;
+                        }
+                        out.write(buffer, 0, readByteCount);
+                    }
+                } catch (FileNotFoundException fnfe) {
+                    Log.e(LOG_TAG, "Error writing print job data!", fnfe);
+                } catch (IOException ioe) {
+                    Log.e(LOG_TAG, "Error writing print job data!", ioe);
+                } finally {
+                    IoUtils.closeQuietly(in);
+                    IoUtils.closeQuietly(out);
+                    IoUtils.closeQuietly(fd);
+                }
+                Log.i(LOG_TAG, "[END WRITE]");
+                return null;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+    }
+
+    public File generateFileForPrintJob(int printJobId) {
+        return new File(getFilesDir(), "print_job_"
+                + printJobId + "." + PRINT_FILE_EXTENSION);
+    }
+
+    private void addPrintJobLocked(PrintJobInfo printJob) {
+        mPrintJobs.add(printJob);
+        if (DEBUG_PRINT_JOB_LIFECYCLE) {
+            Slog.i(LOG_TAG, "[ADD] " + printJob);
+        }
+    }
+
+    private void removePrintJobLocked(PrintJobInfo printJob) {
+        if (mPrintJobs.remove(printJob)) {
+            generateFileForPrintJob(printJob.getId()).delete();
+            if (DEBUG_PRINT_JOB_LIFECYCLE) {
+                Slog.i(LOG_TAG, "[REMOVE] " + printJob);
+            }
+        }
+    }
+
+    public boolean setPrintJobState(int printJobId, int state, String error) {
+        boolean success = false;
+
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                success = true;
+
+                printJob.setState(state);
+                printJob.setFailureReason(error);
+                mNotificationController.onPrintJobStateChanged(printJob);
+
+                if (DEBUG_PRINT_JOB_LIFECYCLE) {
+                    Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
+                }
+
+                switch (state) {
+                    case PrintJobInfo.STATE_COMPLETED:
+                    case PrintJobInfo.STATE_CANCELED:
+                        removePrintJobLocked(printJob);
+                        // $fall-through$
+
+                    case PrintJobInfo.STATE_FAILED: {
+                        PrinterId printerId = printJob.getPrinterId();
+                        if (printerId != null) {
+                            ComponentName service = printerId.getServiceName();
+                            if (!hasActivePrintJobsForServiceLocked(service)) {
+                                sendOnAllPrintJobsForServiceHandled(service);
+                            }
+                        }
+                    } break;
+
+                    case PrintJobInfo.STATE_QUEUED: {
+                        sendOnPrintJobQueued(new PrintJobInfo(printJob));
+                    }  break;
+                }
+
+                if (shouldPersistPrintJob(printJob)) {
+                    mPersistanceManager.writeStateLocked();
+                }
+
+                if (!hasActivePrintJobsLocked()) {
+                    notifyOnAllPrintJobsHandled();
+                }
+            }
+        }
+
+        return success;
+    }
+
+    public boolean hasActivePrintJobsLocked() {
+        final int printJobCount = mPrintJobs.size();
+        for (int i = 0; i < printJobCount; i++) {
+            PrintJobInfo printJob = mPrintJobs.get(i);
+            if (isActiveState(printJob.getState())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean hasActivePrintJobsForServiceLocked(ComponentName service) {
+        final int printJobCount = mPrintJobs.size();
+        for (int i = 0; i < printJobCount; i++) {
+            PrintJobInfo printJob = mPrintJobs.get(i);
+            if (isActiveState(printJob.getState())
+                    && printJob.getPrinterId().getServiceName().equals(service)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isActiveState(int printJobState) {
+        return printJobState == PrintJobInfo.STATE_CREATED
+                || printJobState == PrintJobInfo.STATE_QUEUED
+                || printJobState == PrintJobInfo.STATE_STARTED;
+    }
+
+    public boolean setPrintJobTag(int printJobId, String tag) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                String printJobTag = printJob.getTag();
+                if (printJobTag == null) {
+                    if (tag == null) {
+                        return false;
+                    }
+                } else if (printJobTag.equals(tag)) {
+                    return false;
+                }
+                printJob.setTag(tag);
+                if (shouldPersistPrintJob(printJob)) {
+                    mPersistanceManager.writeStateLocked();
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setPrintJobCopiesNoPersistence(int printJobId, int copies) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                printJob.setCopies(copies);
+            }
+        }
+    }
+
+    public void setPrintJobPrintDocumentInfoNoPersistence(int printJobId, PrintDocumentInfo info) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                printJob.setDocumentInfo(info);
+            }
+        }
+    }
+
+    public void setPrintJobAttributesNoPersistence(int printJobId, PrintAttributes attributes) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                printJob.setAttributes(attributes);
+            }
+        }
+    }
+
+    public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                printJob.setPrinterId(printer.getId());
+                printJob.setPrinterName(printer.getName());
+            }
+        }
+    }
+
+    public void setPrintJobPagesNoPersistence(int printJobId, PageRange[] pages) {
+        synchronized (mLock) {
+            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+            if (printJob != null) {
+                printJob.setPages(pages);
+            }
+        }
+    }
+
+    private boolean shouldPersistPrintJob(PrintJobInfo printJob) {
+        return printJob.getState() >= PrintJobInfo.STATE_QUEUED;
+    }
+
+    private void notifyOnAllPrintJobsHandled() {
+        // This has to run on the tread that is persisting the current state
+        // since this call may result in the system unbinding from the spooler
+        // and as a result the spooler process may get killed before the write
+        // completes.
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                sendOnAllPrintJobsHandled();
+                return null;
+            }
+        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+    }
+
+    private final class PersistenceManager {
+        private static final String PERSIST_FILE_NAME = "print_spooler_state.xml";
+
+        private static final String TAG_SPOOLER = "spooler";
+        private static final String TAG_JOB = "job";
+
+        private static final String TAG_PRINTER_ID = "printerId";
+        private static final String TAG_PAGE_RANGE = "pageRange";
+        private static final String TAG_ATTRIBUTES = "attributes";
+        private static final String TAG_DOCUMENT_INFO = "documentInfo";
+
+        private static final String ATTR_ID = "id";
+        private static final String ATTR_LABEL = "label";
+        private static final String ATTR_STATE = "state";
+        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_COPIES = "copies";
+
+        private static final String TAG_MEDIA_SIZE = "mediaSize";
+        private static final String TAG_RESOLUTION = "resolution";
+        private static final String TAG_MARGINS = "margins";
+        private static final String TAG_INPUT_TRAY = "inputTray";
+        private static final String TAG_OUTPUT_TRAY = "outputTray";
+
+        private static final String ATTR_DUPLEX_MODE = "duplexMode";
+        private static final String ATTR_COLOR_MODE = "colorMode";
+        private static final String ATTR_FITTING_MODE = "fittingMode";
+        private static final String ATTR_ORIENTATION = "orientation";
+
+        private static final String ATTR_LOCAL_ID = "printerName";
+        private static final String ATTR_SERVICE_NAME = "serviceName";
+
+        private static final String ATTR_WIDTH_MILS = "widthMils";
+        private static final String ATTR_HEIGHT_MILS = "heightMils";
+
+        private static final String ATTR_HORIZONTAL_DPI = "horizontalDip";
+        private static final String ATTR_VERTICAL_DPI = "verticalDpi";
+
+        private static final String ATTR_LEFT_MILS = "leftMils";
+        private static final String ATTR_TOP_MILS = "topMils";
+        private static final String ATTR_RIGHT_MILS = "rightMils";
+        private static final String ATTR_BOTTOM_MILS = "bottomMils";
+
+        private static final String ATTR_START = "start";
+        private static final String ATTR_END = "end";
+
+        private static final String ATTR_NAME = "name";
+        private static final String ATTR_PAGE_COUNT = "pageCount";
+        private static final String ATTR_CONTENT_TYPE = "contentType";
+
+        private final AtomicFile mStatePersistFile;
+
+        private boolean mWriteStateScheduled;
+
+        private PersistenceManager() {
+            mStatePersistFile = new AtomicFile(new File(getFilesDir(),
+                    PERSIST_FILE_NAME));
+        }
+
+        public void writeStateLocked() {
+            if (!PERSISTNECE_MANAGER_ENABLED) {
+                return;
+            }
+            if (mWriteStateScheduled) {
+                return;
+            }
+            mWriteStateScheduled = true;
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    synchronized (mLock) {
+                        mWriteStateScheduled = false;
+                        doWriteStateLocked();
+                    }
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+        }
+
+        private void doWriteStateLocked() {
+            if (DEBUG_PERSISTENCE) {
+                Log.i(LOG_TAG, "[PERSIST START]");
+            }
+            FileOutputStream out = null;
+            try {
+                out = mStatePersistFile.startWrite();
+
+                XmlSerializer serializer = new FastXmlSerializer();
+                serializer.setOutput(out, "utf-8");
+                serializer.startDocument(null, true);
+                serializer.startTag(null, TAG_SPOOLER);
+
+                List<PrintJobInfo> printJobs = mPrintJobs;
+
+                final int printJobCount = printJobs.size();
+                for (int j = 0; j < printJobCount; j++) {
+                    PrintJobInfo printJob = printJobs.get(j);
+
+                    final int state = printJob.getState();
+                    if (state < PrintJobInfo.STATE_QUEUED
+                            || state > PrintJobInfo.STATE_CANCELED) {
+                        continue;
+                    }
+
+                    serializer.startTag(null, TAG_JOB);
+
+                    serializer.attribute(null, ATTR_ID, String.valueOf(printJob.getId()));
+                    serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString());
+                    serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState()));
+                    serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId()));
+                    serializer.attribute(null, ATTR_USER_ID, String.valueOf(printJob.getUserId()));
+                    String tag = printJob.getTag();
+                    if (tag != null) {
+                        serializer.attribute(null, ATTR_TAG, tag);
+                    }
+                    serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies()));
+
+                    PrinterId printerId = printJob.getPrinterId();
+                    if (printerId != null) {
+                        serializer.startTag(null, TAG_PRINTER_ID);
+                        serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
+                        serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
+                                .flattenToString());
+                        serializer.endTag(null, TAG_PRINTER_ID);
+                    }
+
+                    PageRange[] pages = printJob.getPages();
+                    if (pages != null) {
+                        for (int i = 0; i < pages.length; i++) {
+                            serializer.startTag(null, TAG_PAGE_RANGE);
+                            serializer.attribute(null, ATTR_START, String.valueOf(
+                                    pages[i].getStart()));
+                            serializer.attribute(null, ATTR_END, String.valueOf(
+                                    pages[i].getEnd()));
+                            serializer.endTag(null, TAG_PAGE_RANGE);
+                        }
+                    }
+
+                    PrintAttributes attributes = printJob.getAttributes();
+                    if (attributes != null) {
+                        serializer.startTag(null, TAG_ATTRIBUTES);
+
+                        final int duplexMode = attributes.getDuplexMode();
+                        serializer.attribute(null, ATTR_DUPLEX_MODE,
+                                String.valueOf(duplexMode));
+
+                        final int colorMode = attributes.getColorMode();
+                        serializer.attribute(null, ATTR_COLOR_MODE,
+                                String.valueOf(colorMode));
+
+                        final int fittingMode = attributes.getFittingMode();
+                        serializer.attribute(null, ATTR_FITTING_MODE,
+                                String.valueOf(fittingMode));
+
+                        final int orientation = attributes.getOrientation();
+                        serializer.attribute(null, ATTR_ORIENTATION,
+                                String.valueOf(orientation));
+
+                        MediaSize mediaSize = attributes.getMediaSize();
+                        if (mediaSize != null) {
+                            serializer.startTag(null, TAG_MEDIA_SIZE);
+                            serializer.attribute(null, ATTR_ID, mediaSize.getId());
+                            serializer.attribute(null, ATTR_LABEL, mediaSize.getLabel()
+                                    .toString());
+                            serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf(
+                                    mediaSize.getWidthMils()));
+                            serializer.attribute(null, ATTR_HEIGHT_MILS, String.valueOf(
+                                    mediaSize.getHeightMils()));
+                            serializer.endTag(null, TAG_MEDIA_SIZE);
+                        }
+
+                        Resolution resolution = attributes.getResolution();
+                        if (resolution != null) {
+                            serializer.startTag(null, TAG_RESOLUTION);
+                            serializer.attribute(null, ATTR_ID, resolution.getId());
+                            serializer.attribute(null, ATTR_LABEL, resolution.getLabel()
+                                    .toString());
+                            serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf(
+                                    resolution.getHorizontalDpi()));
+                            serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
+                                    resolution.getVerticalDpi()));
+                            serializer.endTag(null, TAG_RESOLUTION);
+                        }
+
+                        Margins margins = attributes.getMargins();
+                        if (margins != null) {
+                            serializer.startTag(null, TAG_MARGINS);
+                            serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf(
+                                    margins.getLeftMils()));
+                            serializer.attribute(null, ATTR_TOP_MILS, String.valueOf(
+                                    margins.getTopMils()));
+                            serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf(
+                                    margins.getRightMils()));
+                            serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf(
+                                    margins.getBottomMils()));
+                            serializer.endTag(null, TAG_MARGINS);
+                        }
+
+                        Tray inputTray = attributes.getInputTray();
+                        if (inputTray != null) {
+                            serializer.startTag(null, TAG_INPUT_TRAY);
+                            serializer.attribute(null, ATTR_ID, inputTray.getId());
+                            serializer.attribute(null, ATTR_LABEL, inputTray.getLabel()
+                                    .toString());
+                            serializer.endTag(null, TAG_INPUT_TRAY);
+                        }
+
+                        Tray outputTray = attributes.getOutputTray();
+                        if (outputTray != null) {
+                            serializer.startTag(null, TAG_OUTPUT_TRAY);
+                            serializer.attribute(null, ATTR_ID, outputTray.getId());
+                            serializer.attribute(null, ATTR_LABEL, outputTray.getLabel()
+                                    .toString());
+                            serializer.endTag(null, TAG_OUTPUT_TRAY);
+                        }
+
+                        serializer.endTag(null, TAG_ATTRIBUTES);
+                    }
+
+                    PrintDocumentInfo documentInfo = printJob.getDocumentInfo();
+                    if (documentInfo != null) {
+                        serializer.startTag(null, TAG_DOCUMENT_INFO);
+                        serializer.attribute(null, ATTR_NAME, documentInfo.getName());
+                        serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf(
+                                documentInfo.getContentType()));
+                        serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf(
+                                documentInfo.getPageCount()));
+                        serializer.endTag(null, TAG_DOCUMENT_INFO);
+                    }
+
+                    serializer.endTag(null, TAG_JOB);
+
+                    if (DEBUG_PERSISTENCE) {
+                        Log.i(LOG_TAG, "[PERSISTED] " + printJob);
+                    }
+                }
+
+                serializer.endTag(null, TAG_SPOOLER);
+                serializer.endDocument();
+                mStatePersistFile.finishWrite(out);
+                if (DEBUG_PERSISTENCE) {
+                    Log.i(LOG_TAG, "[PERSIST END]");
+                }
+            } catch (IOException e) {
+                Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
+                mStatePersistFile.failWrite(out);
+            } finally {
+                IoUtils.closeQuietly(out);
+            }
+        }
+
+        public void readStateLocked() {
+            if (!PERSISTNECE_MANAGER_ENABLED) {
+                return;
+            }
+            FileInputStream in = null;
+            try {
+                in = mStatePersistFile.openRead();
+            } catch (FileNotFoundException e) {
+                Log.i(LOG_TAG, "No existing print spooler state.");
+                return;
+            }
+            try {
+                XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(in, null);
+                parseState(parser);
+            } catch (IllegalStateException ise) {
+                Slog.w(LOG_TAG, "Failed parsing ", ise);
+            } catch (NullPointerException npe) {
+                Slog.w(LOG_TAG, "Failed parsing ", npe);
+            } catch (NumberFormatException nfe) {
+                Slog.w(LOG_TAG, "Failed parsing ", nfe);
+            } catch (XmlPullParserException xppe) {
+                Slog.w(LOG_TAG, "Failed parsing ", xppe);
+            } catch (IOException ioe) {
+                Slog.w(LOG_TAG, "Failed parsing ", ioe);
+            } catch (IndexOutOfBoundsException iobe) {
+                Slog.w(LOG_TAG, "Failed parsing ", iobe);
+            } finally {
+                IoUtils.closeQuietly(in);
+            }
+        }
+
+        private void parseState(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            parser.next();
+            skipEmptyTextTags(parser);
+            expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
+            parser.next();
+
+            while (parsePrintJob(parser)) {
+                parser.next();
+            }
+
+            skipEmptyTextTags(parser);
+            expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
+        }
+
+        private boolean parsePrintJob(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            skipEmptyTextTags(parser);
+            if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
+                return false;
+            }
+
+            PrintJobInfo printJob = new PrintJobInfo();
+
+            final int printJobId = Integer.parseInt(parser.getAttributeValue(null, ATTR_ID));
+            printJob.setId(printJobId);
+            String label = parser.getAttributeValue(null, ATTR_LABEL);
+            printJob.setLabel(label);
+            final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE));
+            printJob.setState(state);
+            final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID));
+            printJob.setAppId(appId);
+            final int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USER_ID));
+            printJob.setUserId(userId);
+            String tag = parser.getAttributeValue(null, ATTR_TAG);
+            printJob.setTag(tag);
+            String copies = parser.getAttributeValue(null, ATTR_COPIES);
+            printJob.setCopies(Integer.parseInt(copies));
+
+            parser.next();
+
+            skipEmptyTextTags(parser);
+            if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
+                String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
+                ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
+                        null, ATTR_SERVICE_NAME));
+                printJob.setPrinterId(new PrinterId(service, localId));
+                parser.next();
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
+                parser.next();
+            }
+
+            skipEmptyTextTags(parser);
+            List<PageRange> pageRanges = null;
+            while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) {
+                final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START));
+                final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END));
+                PageRange pageRange = new PageRange(start, end);
+                if (pageRanges == null) {
+                    pageRanges = new ArrayList<PageRange>();
+                }
+                pageRanges.add(pageRange);
+                parser.next();
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE);
+                parser.next();
+            }
+            if (pageRanges != null) {
+                PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
+                pageRanges.toArray(pageRangesArray);
+                printJob.setPages(pageRangesArray);
+            }
+
+            skipEmptyTextTags(parser);
+            if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) {
+
+                PrintAttributes.Builder builder = new PrintAttributes.Builder();
+
+                String duplexMode = parser.getAttributeValue(null, ATTR_DUPLEX_MODE);
+                builder.setDuplexMode(Integer.parseInt(duplexMode));
+
+                String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
+                builder.setColorMode(Integer.parseInt(colorMode));
+
+                String fittingMode = parser.getAttributeValue(null, ATTR_FITTING_MODE);
+                builder.setFittingMode(Integer.parseInt(fittingMode));
+
+                String orientation = parser.getAttributeValue(null, ATTR_ORIENTATION);
+                builder.setOrientation(Integer.parseInt(orientation));
+
+                parser.next();
+
+                skipEmptyTextTags(parser);
+                if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) {
+                    String id = parser.getAttributeValue(null, ATTR_ID);
+                    label = parser.getAttributeValue(null, ATTR_LABEL);
+                    final int widthMils = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_WIDTH_MILS));
+                    final int heightMils = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_HEIGHT_MILS));
+                    MediaSize mediaSize = new MediaSize(id, label, widthMils, heightMils);
+                    builder.setMediaSize(mediaSize);
+                    parser.next();
+                    skipEmptyTextTags(parser);
+                    expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE);
+                    parser.next();
+                }
+
+                skipEmptyTextTags(parser);
+                if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) {
+                    String id = parser.getAttributeValue(null, ATTR_ID);
+                    label = parser.getAttributeValue(null, ATTR_LABEL);
+                    final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_HORIZONTAL_DPI));
+                    final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_VERTICAL_DPI));
+                    Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
+                    builder.setResolution(resolution);
+                    parser.next();
+                    skipEmptyTextTags(parser);
+                    expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION);
+                    parser.next();
+                }
+
+                skipEmptyTextTags(parser);
+                if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) {
+                    final int leftMils = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_LEFT_MILS));
+                    final int topMils = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_TOP_MILS));
+                    final int rightMils = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_RIGHT_MILS));
+                    final int bottomMils = Integer.parseInt(parser.getAttributeValue(null,
+                            ATTR_BOTTOM_MILS));
+                    Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils);
+                    builder.setMargins(margins);
+                    parser.next();
+                    skipEmptyTextTags(parser);
+                    expect(parser, XmlPullParser.END_TAG, TAG_MARGINS);
+                    parser.next();
+                }
+
+                skipEmptyTextTags(parser);
+                if (accept(parser, XmlPullParser.START_TAG, TAG_INPUT_TRAY)) {
+                    String id = parser.getAttributeValue(null, ATTR_ID);
+                    label = parser.getAttributeValue(null, ATTR_LABEL);
+                    Tray tray = new Tray(id, label);
+                    builder.setInputTray(tray);
+                    parser.next();
+                    skipEmptyTextTags(parser);
+                    expect(parser, XmlPullParser.END_TAG, TAG_INPUT_TRAY);
+                    parser.next();
+                }
+
+                skipEmptyTextTags(parser);
+                if (accept(parser, XmlPullParser.START_TAG, TAG_OUTPUT_TRAY)) {
+                    String id = parser.getAttributeValue(null, ATTR_ID);
+                    label = parser.getAttributeValue(null, ATTR_LABEL);
+                    Tray tray = new Tray(id, label);
+                    builder.setOutputTray(tray);
+                    parser.next();
+                    skipEmptyTextTags(parser);
+                    expect(parser, XmlPullParser.END_TAG, TAG_OUTPUT_TRAY);
+                    parser.next();
+                }
+
+                printJob.setAttributes(builder.create());
+
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
+                parser.next();
+            }
+
+            skipEmptyTextTags(parser);
+            if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
+                String name = parser.getAttributeValue(null, ATTR_NAME);
+                final int pageCount = Integer.parseInt(parser.getAttributeValue(null,
+                        ATTR_PAGE_COUNT));
+                final int contentType = Integer.parseInt(parser.getAttributeValue(null,
+                        ATTR_CONTENT_TYPE));
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
+                        .setPageCount(pageCount)
+                        .setContentType(contentType).create();
+                printJob.setDocumentInfo(info);
+                parser.next();
+                skipEmptyTextTags(parser);
+                expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO);
+                parser.next();
+            }
+
+            mPrintJobs.add(printJob);
+
+            if (DEBUG_PERSISTENCE) {
+                Log.i(LOG_TAG, "[RESTORED] " + printJob);
+            }
+
+            skipEmptyTextTags(parser);
+            expect(parser, XmlPullParser.END_TAG, TAG_JOB);
+
+            return true;
+        }
+
+        private void expect(XmlPullParser parser, int type, String tag)
+                throws IOException, XmlPullParserException {
+            if (!accept(parser, type, tag)) {
+                throw new XmlPullParserException("Exepected event: " + type
+                        + " and tag: " + tag + " but got event: " + parser.getEventType()
+                        + " and tag:" + parser.getName());
+            }
+        }
+
+        private void skipEmptyTextTags(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            while (accept(parser, XmlPullParser.TEXT, null)
+                    && "\n".equals(parser.getText())) {
+                parser.next();
+            }
+        }
+
+        private boolean accept(XmlPullParser parser, int type, String tag)
+                throws IOException, XmlPullParserException {
+            if (parser.getEventType() != type) {
+                return false;
+            }
+            if (tag != null) {
+                if (!tag.equals(parser.getName())) {
+                    return false;
+                }
+            } else if (parser.getName() != null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public static abstract class PrinterDiscoverySession {
+
+        private PrintSpoolerService mService;
+
+        private boolean mIsStarted;
+
+        public PrinterDiscoverySession() {
+            mService = PrintSpoolerService.peekInstance();
+            mService.createPrinterDiscoverySession();
+            mService.setPrinterDiscoverySessionClient(this);
+        }
+
+        public final void startPrinterDisovery(List<PrinterId> priorityList) {
+            mIsStarted = true;
+            mService.startPrinterDiscovery(priorityList);
+        }
+
+        public final void stopPrinterDiscovery() {
+            mIsStarted = false;
+            mService.stopPrinterDiscovery();
+        }
+
+        public void requestPrinterUpdated(PrinterId printerId) {
+            mService.requestPrinterUpdate(printerId);
+        }
+
+        public final void destroy() {
+            mService.setPrinterDiscoverySessionClient(null);
+            mService.destroyPrinterDiscoverySession();
+        }
+
+        public final boolean isStarted() {
+            return mIsStarted;
+        }
+
+        public abstract void onPrintersAdded(List<PrinterInfo> printers);
+
+        public abstract void onPrintersRemoved(List<PrinterId> printerIds);
+
+        public abstract void onPrintersUpdated(List<PrinterInfo> printers);
+    }
 }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java
new file mode 100644
index 0000000..141dbd1
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.print.PrinterId;
+
+import com.android.printspooler.SelectPrinterFragment.OnPrinterSelectedListener;
+
+public class SelectPrinterActivity extends Activity implements OnPrinterSelectedListener {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.select_printer_activity);
+    }
+
+    @Override
+    public void onPrinterSelected(PrinterId printer) {
+        Intent intent = new Intent();
+        intent.putExtra(PrintJobConfigActivity.INTENT_EXTRA_PRINTER_ID, printer);
+        setResult(RESULT_OK, intent);
+        finish();
+    }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
new file mode 100644
index 0000000..9ca3a86
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.app.ListFragment;
+import android.app.LoaderManager;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.Loader;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.printservice.PrintServiceInfo;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.ListView;
+import android.widget.SearchView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This is a fragment for selecting a printer.
+ */
+public final class SelectPrinterFragment extends ListFragment {
+
+    private static final int LOADER_ID_PRINTERS_LOADER = 1;
+
+    private static final String FRAGMRNT_TAG_ADD_PRINTER_DIALOG =
+            "FRAGMRNT_TAG_ADD_PRINTER_DIALOG";
+
+    private static final String FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS =
+            "FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS";
+
+    private final ArrayList<PrintServiceInfo> mAddPrinterServices =
+            new ArrayList<PrintServiceInfo>();
+
+    public static interface OnPrinterSelectedListener {
+        public void onPrinterSelected(PrinterId printerId);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        setListAdapter(new DestinationAdapter());
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        inflater.inflate(R.menu.select_printer_activity, menu);
+
+        MenuItem searchItem = menu.findItem(R.id.action_search);
+        SearchView searchView = (SearchView) searchItem.getActionView();
+        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String query) {
+                return true;
+            }
+
+            @Override
+            public boolean onQueryTextChange(String searchString) {
+                ((DestinationAdapter) getListAdapter()).getFilter().filter(searchString);
+                return true;
+            }
+        });
+
+        if (mAddPrinterServices.isEmpty()) {
+            menu.removeItem(R.id.action_add_printer);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        updateAddPrintersAdapter();
+        getActivity().invalidateOptionsMenu();
+        super.onResume();
+    }
+
+    @Override
+    public void onListItemClick(ListView list, View view, int position, long id) {
+        PrinterInfo printer = (PrinterInfo) list.getAdapter().getItem(position);
+        Activity activity = getActivity();
+        if (activity instanceof OnPrinterSelectedListener) {
+            ((OnPrinterSelectedListener) activity).onPrinterSelected(printer.getId());
+        } else {
+            throw new IllegalStateException("the host activity must implement"
+                    + " OnPrinterSelectedListener");
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == R.id.action_add_printer) {
+            showAddPrinterSelectionDialog();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private void updateAddPrintersAdapter() {
+        mAddPrinterServices.clear();
+
+        // Get all print services.
+        List<ResolveInfo> resolveInfos = getActivity().getPackageManager().queryIntentServices(
+                new Intent(android.printservice.PrintService.SERVICE_INTERFACE),
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+
+        // No print services - done.
+        if (resolveInfos.isEmpty()) {
+            return;
+        }
+
+        // Find the services with valid add printers activities.
+        final int resolveInfoCount = resolveInfos.size();
+        for (int i = 0; i < resolveInfoCount; i++) {
+            ResolveInfo resolveInfo = resolveInfos.get(i);
+
+            PrintServiceInfo printServiceInfo = PrintServiceInfo.create(
+                    resolveInfo, getActivity());
+            String addPrintersActivity = printServiceInfo.getAddPrintersActivityName();
+
+            // No add printers activity declared - done.
+            if (TextUtils.isEmpty(addPrintersActivity)) {
+                continue;
+            }
+
+            ComponentName addPrintersComponentName = new ComponentName(
+                    resolveInfo.serviceInfo.packageName,
+                    addPrintersActivity);
+            Intent addPritnersIntent = new Intent(Intent.ACTION_MAIN)
+                .setComponent(addPrintersComponentName);
+
+            // The add printers activity is valid - add it.
+            if (!getActivity().getPackageManager().queryIntentActivities(
+                    addPritnersIntent, 0).isEmpty()) {
+                mAddPrinterServices.add(printServiceInfo);
+            }
+        }
+    }
+
+    private void showAddPrinterSelectionDialog() {
+        FragmentTransaction transaction = getFragmentManager().beginTransaction();
+        Fragment oldFragment = getFragmentManager().findFragmentByTag(
+                FRAGMRNT_TAG_ADD_PRINTER_DIALOG);
+        if (oldFragment != null) {
+            transaction.remove(oldFragment);
+        }
+        AddPrinterAlertDialogFragment newFragment = new AddPrinterAlertDialogFragment();
+        Bundle arguments = new Bundle();
+        arguments.putParcelableArrayList(FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS,
+                mAddPrinterServices);
+        newFragment.setArguments(arguments);
+        transaction.add(newFragment, FRAGMRNT_TAG_ADD_PRINTER_DIALOG);
+        transaction.commit();
+    }
+
+    public static class AddPrinterAlertDialogFragment extends DialogFragment {
+
+        private static final String DEFAULT_MARKET_QUERY_STRING =
+                "market://search?q=print";
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+                    .setTitle(R.string.choose_print_service);
+
+            final List<PrintServiceInfo> printServices = (List<PrintServiceInfo>) (List<?>)
+                    getArguments().getParcelableArrayList(FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS);
+
+            ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
+                    android.R.layout.simple_list_item_1);
+            final int printServiceCount = printServices.size();
+            for (int i = 0; i < printServiceCount; i++) {
+                PrintServiceInfo printService = printServices.get(i);
+                adapter.add(printService.getResolveInfo().loadLabel(
+                        getActivity().getPackageManager()).toString());
+            }
+
+            builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    PrintServiceInfo printService = printServices.get(which);
+                    ComponentName componentName = new ComponentName(
+                            printService.getResolveInfo().serviceInfo.packageName,
+                            printService.getAddPrintersActivityName());
+                    Intent intent = new Intent(Intent.ACTION_MAIN);
+                    intent.setComponent(componentName);
+                    startActivity(intent);
+                }
+            });
+
+            Uri marketUri = Uri.parse(DEFAULT_MARKET_QUERY_STRING);
+            final Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
+            if (getActivity().getPackageManager().resolveActivity(marketIntent, 0) != null) {
+                builder.setPositiveButton(R.string.search_play_store,
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int whichButton) {
+                            startActivity(marketIntent);
+                        }
+                    });
+            }
+
+            return builder.create();
+        }
+    }
+
+    private final class DestinationAdapter extends BaseAdapter
+            implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {
+
+        private final Object mLock = new Object();
+
+        private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
+
+        private final List<PrinterInfo> mFilteredPrinters = new ArrayList<PrinterInfo>();
+
+        private CharSequence mLastSearchString;
+
+        public DestinationAdapter() {
+            getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
+        }
+
+        @Override
+        public Filter getFilter() {
+            return new Filter() {
+                @Override
+                protected FilterResults performFiltering(CharSequence constraint) {
+                    synchronized (mLock) {
+                        if (TextUtils.isEmpty(constraint)) {
+                            return null;
+                        }
+                        FilterResults results = new FilterResults();
+                        List<PrinterInfo> filteredPrinters = new ArrayList<PrinterInfo>();
+                        String constraintLowerCase = constraint.toString().toLowerCase();
+                        final int printerCount = mPrinters.size();
+                        for (int i = 0; i < printerCount; i++) {
+                            PrinterInfo printer = mPrinters.get(i);
+                            if (printer.getName().toLowerCase().contains(constraintLowerCase)) {
+                                filteredPrinters.add(printer);
+                            }
+                        }
+                        results.values = filteredPrinters;
+                        results.count = filteredPrinters.size();
+                        return results;
+                    }
+                }
+
+                @Override
+                @SuppressWarnings("unchecked")
+                protected void publishResults(CharSequence constraint, FilterResults results) {
+                    synchronized (mLock) {
+                        mLastSearchString = constraint;
+                        mFilteredPrinters.clear();
+                        if (results == null) {
+                            mFilteredPrinters.addAll(mPrinters);
+                        } else {
+                            List<PrinterInfo> printers = (List<PrinterInfo>) results.values;
+                            mFilteredPrinters.addAll(printers);
+                        }
+                    }
+                    notifyDataSetChanged();
+                }
+            };
+        }
+
+        @Override
+        public int getCount() {
+            synchronized (mLock) {
+                return mFilteredPrinters.size();
+            }
+        }
+
+        @Override
+        public Object getItem(int position) {
+            synchronized (mLock) {
+                return mFilteredPrinters.get(position);
+            }
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getDropDownView(int position, View convertView,
+                ViewGroup parent) {
+            return getView(position, convertView, parent);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = getActivity().getLayoutInflater().inflate(
+                        R.layout.spinner_dropdown_item, parent, false);
+            }
+
+            CharSequence title = null;
+            CharSequence subtitle = null;
+
+            PrinterInfo printer = (PrinterInfo) getItem(position);
+            title = printer.getName();
+            try {
+                PackageManager pm = getActivity().getPackageManager();
+                PackageInfo packageInfo = pm.getPackageInfo(printer.getId()
+                        .getServiceName().getPackageName(), 0);
+                subtitle = packageInfo.applicationInfo.loadLabel(pm);
+            } catch (NameNotFoundException nnfe) {
+                /* ignore */
+            }
+
+            TextView titleView = (TextView) convertView.findViewById(R.id.title);
+            titleView.setText(title);
+
+            TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle);
+            if (!TextUtils.isEmpty(subtitle)) {
+                subtitleView.setText(subtitle);
+                subtitleView.setVisibility(View.VISIBLE);
+            } else {
+                subtitleView.setText(null);
+                subtitleView.setVisibility(View.GONE);
+            }
+
+            return convertView;
+        }
+
+        @Override
+        public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
+            if (id == LOADER_ID_PRINTERS_LOADER) {
+                return new FusedPrintersProvider(getActivity());
+            }
+            return null;
+        }
+
+        @Override
+        public void onLoadFinished(Loader<List<PrinterInfo>> loader,
+                List<PrinterInfo> printers) {
+            synchronized (mLock) {
+                mPrinters.clear();
+                mPrinters.addAll(printers);
+                mFilteredPrinters.clear();
+                mFilteredPrinters.addAll(printers);
+                if (!TextUtils.isEmpty(mLastSearchString)) {
+                    getFilter().filter(mLastSearchString);
+                }
+            }
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
+            synchronized (mLock) {
+                mPrinters.clear();
+                mFilteredPrinters.clear();
+            }
+            notifyDataSetInvalidated();
+        }
+    }
+}
diff --git a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_diagram.png b/packages/SystemUI/res/drawable-hdpi/compat_mode_help_diagram.png
deleted file mode 100644
index 944b1f0..0000000
--- a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_diagram.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_divider_bottom.9.png b/packages/SystemUI/res/drawable-hdpi/compat_mode_help_divider_bottom.9.png
deleted file mode 100644
index 155a315..0000000
--- a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_divider_bottom.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_divider_top.9.png b/packages/SystemUI/res/drawable-hdpi/compat_mode_help_divider_top.9.png
deleted file mode 100644
index 3eb6fa2..0000000
--- a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_divider_top.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_icon.png b/packages/SystemUI/res/drawable-hdpi/compat_mode_help_icon.png
deleted file mode 100644
index 46bb891..0000000
--- a/packages/SystemUI/res/drawable-hdpi/compat_mode_help_icon.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_off.png b/packages/SystemUI/res/drawable-hdpi/hd_off.png
deleted file mode 100644
index e7246cb..0000000
--- a/packages/SystemUI/res/drawable-hdpi/hd_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_on.png b/packages/SystemUI/res/drawable-hdpi/hd_on.png
deleted file mode 100644
index 5360d42..0000000
--- a/packages/SystemUI/res/drawable-hdpi/hd_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_certificate_info.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_certificate_info.png
new file mode 100644
index 0000000..b1e0ff4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_certificate_info.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
deleted file mode 100644
index 7096b73..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
deleted file mode 100644
index e72fde8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index 2a94b5d..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
deleted file mode 100644
index 02da243..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
deleted file mode 100644
index d645a3c..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
deleted file mode 100644
index 5503df1..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
deleted file mode 100644
index 67f16b9..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
deleted file mode 100644
index a59c844..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
deleted file mode 100644
index 017145e..0000000
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
deleted file mode 100644
index 7466d1d..0000000
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_0.png
deleted file mode 100644
index db07305..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
deleted file mode 100644
index 4518ad5..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_1.png
deleted file mode 100644
index 3b6f74ad..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
deleted file mode 100644
index 396d51d..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_2.png
deleted file mode 100644
index bb90a95..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
deleted file mode 100644
index 34dc19f..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_3.png
deleted file mode 100644
index 64c2de2..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
deleted file mode 100644
index 9d93d2b..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_4.png
deleted file mode 100644
index 28ae311..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_4_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
deleted file mode 100644
index cd4f706..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_in.png
deleted file mode 100644
index cbce322..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_inout.png
deleted file mode 100644
index 6788da8..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_null.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_null.png
deleted file mode 100644
index 0f00fb0..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_out.png
deleted file mode 100644
index db05c5f..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-hdpi/ic_sysbar_signal_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_0.png
deleted file mode 100644
index 9b99940..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
deleted file mode 100644
index 2cd8c90..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_1.png
deleted file mode 100644
index f5363c3..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
deleted file mode 100644
index ded5029..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_2.png
deleted file mode 100644
index 01f4eb0..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
deleted file mode 100644
index 9963e97..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_3.png
deleted file mode 100644
index 3123cc9..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
deleted file mode 100644
index 34363fa..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_4.png
deleted file mode 100644
index 186844c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_4_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
deleted file mode 100644
index 680f806..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_in.png
deleted file mode 100644
index 4d5bb0b..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_inout.png
deleted file mode 100644
index 253d15c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_null.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_null.png
deleted file mode 100644
index 5d688aa..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_out.png
deleted file mode 100644
index 8198fdc..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-mdpi/ic_sysbar_signal_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_0.png
deleted file mode 100644
index a8691dc..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
deleted file mode 100644
index 77ade2f..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_1.png
deleted file mode 100644
index 0974b2c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
deleted file mode 100644
index 4be5612..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_2.png
deleted file mode 100644
index 79f8b88..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
deleted file mode 100644
index 6167246..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_3.png
deleted file mode 100644
index d2ecd47..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
deleted file mode 100644
index 92871c3..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_4.png
deleted file mode 100644
index 4b86ca4..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
deleted file mode 100644
index 200d1cb..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_in.png
deleted file mode 100644
index f4c5281..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_inout.png
deleted file mode 100644
index 42e2170..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_null.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_null.png
deleted file mode 100644
index eaff2c0..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_out.png
deleted file mode 100644
index 9feb041..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw720dp-xhdpi/ic_sysbar_signal_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_diagram.png b/packages/SystemUI/res/drawable-mdpi/compat_mode_help_diagram.png
deleted file mode 100644
index 5f08b52..0000000
--- a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_diagram.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_divider_bottom.9.png b/packages/SystemUI/res/drawable-mdpi/compat_mode_help_divider_bottom.9.png
deleted file mode 100644
index b7f4523..0000000
--- a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_divider_bottom.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_divider_top.9.png b/packages/SystemUI/res/drawable-mdpi/compat_mode_help_divider_top.9.png
deleted file mode 100644
index fae17b1..0000000
--- a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_divider_top.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_icon.png b/packages/SystemUI/res/drawable-mdpi/compat_mode_help_icon.png
deleted file mode 100644
index e017e03..0000000
--- a/packages/SystemUI/res/drawable-mdpi/compat_mode_help_icon.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_off.png b/packages/SystemUI/res/drawable-mdpi/hd_off.png
deleted file mode 100644
index 6c01b8a..0000000
--- a/packages/SystemUI/res/drawable-mdpi/hd_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_on.png b/packages/SystemUI/res/drawable-mdpi/hd_on.png
deleted file mode 100644
index de878ef..0000000
--- a/packages/SystemUI/res/drawable-mdpi/hd_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_certificate_info.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_certificate_info.png
new file mode 100644
index 0000000..d7104c5a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_certificate_info.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
deleted file mode 100644
index c33271b..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
deleted file mode 100644
index 4dbca6d..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index 238df06..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
deleted file mode 100644
index 9c117ae..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
deleted file mode 100644
index 4f51201..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
deleted file mode 100644
index 81c0c10..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
deleted file mode 100644
index 436f16d..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
deleted file mode 100644
index 876d9ee..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
deleted file mode 100644
index 1fd5dd3..0000000
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
deleted file mode 100644
index b2edd46..0000000
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/compat_mode_help_bg.png b/packages/SystemUI/res/drawable-nodpi/compat_mode_help_bg.png
deleted file mode 100644
index 87d8c41..0000000
--- a/packages/SystemUI/res/drawable-nodpi/compat_mode_help_bg.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_brightness.png
deleted file mode 100644
index 77eae9a..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_brightness.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_brightness.png
deleted file mode 100644
index f5fcb04..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_brightness.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_brightness.png
deleted file mode 100644
index f3dfb4f..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_brightness.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png
deleted file mode 100644
index 2f4cf9d9..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png
deleted file mode 100644
index 80184ab..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png
deleted file mode 100644
index f33f00e..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png
deleted file mode 100644
index 7f16039e..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png
deleted file mode 100644
index 83bfd39..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png
deleted file mode 100644
index 2c85bcf..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png
deleted file mode 100644
index ce1acbd..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png
deleted file mode 100644
index df53bb0..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png
deleted file mode 100644
index 44d8726..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png
deleted file mode 100644
index 1a060e7..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png
deleted file mode 100644
index 02fd013..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png
deleted file mode 100644
index 496c5af..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png
deleted file mode 100644
index e371412..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png
deleted file mode 100644
index 13a0141..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png
deleted file mode 100644
index bc6344a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png
deleted file mode 100644
index 3a1bc96..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png
deleted file mode 100644
index 12f5b99..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_battery_charge_anim85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png
deleted file mode 100644
index 31762a2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png
deleted file mode 100644
index c4376a2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_bluetooth_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png
deleted file mode 100644
index 5691427..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_1x.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png
deleted file mode 100644
index 2464d9e..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_3g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png
deleted file mode 100644
index ffe90bc..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_4g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png
deleted file mode 100644
index 823b3fa3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_e.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png
deleted file mode 100644
index 1ac455c..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png
deleted file mode 100644
index 7a38b12..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_h.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png
deleted file mode 100644
index 3861bfe..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_connected_roam.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png
deleted file mode 100644
index 2eb6246..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_1x.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png
deleted file mode 100644
index 0ce5ec3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_3g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png
deleted file mode 100644
index 6bf2412..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_4g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png
deleted file mode 100644
index 791de4d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_e.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png
deleted file mode 100644
index 0712aa6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png
deleted file mode 100644
index 2886e55..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_data_fully_connected_h.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png
deleted file mode 100644
index ac322ba..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
deleted file mode 100644
index ac322ba..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_0_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png
deleted file mode 100644
index f139bbe..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
deleted file mode 100644
index af67018..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png
deleted file mode 100644
index fe404e2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
deleted file mode 100644
index 1ffa9b6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png
deleted file mode 100644
index 75cd8ee..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
deleted file mode 100644
index 666d1f6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png
deleted file mode 100644
index da9607b..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
deleted file mode 100644
index d05297f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png
deleted file mode 100644
index 64d4e60..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png
deleted file mode 100644
index 3d67766..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png
deleted file mode 100644
index b74e070..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png
deleted file mode 100644
index 709b181..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png
deleted file mode 100644
index 24485e1..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_signal_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png
deleted file mode 100644
index 390d500..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png
deleted file mode 100644
index 78998f9..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png
deleted file mode 100644
index c539615..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png
deleted file mode 100644
index 57675a2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png
deleted file mode 100644
index eec0390..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png
deleted file mode 100644
index 900867a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png
deleted file mode 100644
index 253bdac..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png
deleted file mode 100644
index b50576c..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png
deleted file mode 100644
index d69a171..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png
deleted file mode 100644
index 47df06f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png
deleted file mode 100644
index 99184f0..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png
deleted file mode 100644
index 4a2ac51..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png
deleted file mode 100644
index 4fd3a08..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_wifi_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_zoom_default.png
deleted file mode 100644
index 348afb5..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_zoom_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_zoom_pressed.png
deleted file mode 100644
index 2f20d67..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/ic_sysbar_zoom_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/recents_bg_protect_tile.png
deleted file mode 100644
index a57c27a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/recents_bg_protect_tile.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png
deleted file mode 100644
index 9b7c5d6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png
deleted file mode 100644
index ea2918f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png
deleted file mode 100644
index 906c818..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png
deleted file mode 100644
index c855fa599d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png
deleted file mode 100644
index cafa16f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png
deleted file mode 100644
index 400c2ca..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png
deleted file mode 100644
index 1aa0d82..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png
deleted file mode 100644
index ac0bca1..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png
deleted file mode 100644
index 2e76eee..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png
deleted file mode 100644
index 8d54b97..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png
deleted file mode 100644
index 784c4e7..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png
deleted file mode 100644
index 6bc543c..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png
deleted file mode 100644
index ba449ac..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png
deleted file mode 100644
index 13399f4..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png
deleted file mode 100644
index e2a95ef..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png
deleted file mode 100644
index 4c8ac28..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png
deleted file mode 100644
index b3b9f52..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_battery_charge_anim85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png
deleted file mode 100644
index c4f0d78..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png
deleted file mode 100644
index 3034a47..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_bluetooth_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png
deleted file mode 100644
index 5287c0f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_1x.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png
deleted file mode 100644
index d8a5ee8..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_3g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png
deleted file mode 100644
index 11737ee..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_4g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png
deleted file mode 100644
index 842faacd..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_e.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png
deleted file mode 100644
index 0548dd3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png
deleted file mode 100644
index be79e0d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_h.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png
deleted file mode 100644
index ee2e99e..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_connected_roam.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png
deleted file mode 100644
index ee43332d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_1x.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png
deleted file mode 100644
index 4e38c5d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_3g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png
deleted file mode 100644
index 6c08aa9..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_4g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png
deleted file mode 100644
index 2e7c46d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_e.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png
deleted file mode 100644
index 57f48fb..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png
deleted file mode 100644
index f751a31..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_data_fully_connected_h.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png
deleted file mode 100644
index f931c60..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
deleted file mode 100644
index f931c60..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_0_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png
deleted file mode 100644
index 398f4d5..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
deleted file mode 100644
index a0fc3f2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png
deleted file mode 100644
index 5fe96a3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
deleted file mode 100644
index 8a66255..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png
deleted file mode 100644
index e785a7a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
deleted file mode 100644
index 63be95d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png
deleted file mode 100644
index 533bcdc..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
deleted file mode 100644
index 566172e..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png
deleted file mode 100644
index f61c058..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png
deleted file mode 100644
index 5c38d45..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png
deleted file mode 100644
index 6a79695..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png
deleted file mode 100644
index 67d5cbf..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png
deleted file mode 100644
index 99dbe1b..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_signal_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png
deleted file mode 100644
index 6a73a89..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png
deleted file mode 100644
index 7042f2b..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png
deleted file mode 100644
index 3da781e8..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png
deleted file mode 100644
index 1570dd2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png
deleted file mode 100644
index 80a7a4a7..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png
deleted file mode 100644
index 9db1a84..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png
deleted file mode 100644
index f9720f2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png
deleted file mode 100644
index 8567d11..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png
deleted file mode 100644
index 5ee6d07..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png
deleted file mode 100644
index b38f7eb..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png
deleted file mode 100644
index ec6e805..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png
deleted file mode 100644
index 9a79c54..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png
deleted file mode 100644
index 1943e8c..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_wifi_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_zoom_default.png
deleted file mode 100644
index 89d486f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_zoom_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_zoom_pressed.png
deleted file mode 100644
index b134436..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/ic_sysbar_zoom_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/recents_bg_protect_tile.png
deleted file mode 100644
index 87c7be6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/recents_bg_protect_tile.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png
deleted file mode 100644
index 0f83f7a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png
deleted file mode 100644
index 511923c..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png
deleted file mode 100644
index 61fa300..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png
deleted file mode 100644
index daefb7c..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png
deleted file mode 100644
index bc8c467..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png
deleted file mode 100644
index a16c979..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png
deleted file mode 100644
index 4778dc1..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png
deleted file mode 100644
index 81693b6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png
deleted file mode 100644
index e81bb8d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png
deleted file mode 100644
index 9834f5a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png
deleted file mode 100644
index b314f8b..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png
deleted file mode 100644
index 59de3f2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png
deleted file mode 100644
index 91397ed..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png
deleted file mode 100644
index 268fea4..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png
deleted file mode 100644
index 15ee476..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png
deleted file mode 100644
index 4dead31..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png
deleted file mode 100644
index 8b4563f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_battery_charge_anim85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png
deleted file mode 100644
index 2984394..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png
deleted file mode 100644
index 4b904b4..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_bluetooth_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png
deleted file mode 100644
index 31af3c2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_1x.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png
deleted file mode 100644
index 4f5fa70..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_3g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png
deleted file mode 100644
index e7eb85e5..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_4g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png
deleted file mode 100644
index 79038f7..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_e.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png
deleted file mode 100644
index c554b23..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png
deleted file mode 100644
index e5c0780f0..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_h.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png
deleted file mode 100644
index 0edc9b5..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_connected_roam.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png
deleted file mode 100644
index de93431..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_1x.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png
deleted file mode 100644
index 9b01f30..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_3g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png
deleted file mode 100644
index a44d3a2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_4g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png
deleted file mode 100644
index a4a93e3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_e.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png
deleted file mode 100644
index 4f6f1ba..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_g.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png
deleted file mode 100644
index bc135c3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_data_fully_connected_h.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png
deleted file mode 100644
index ccf1ba1..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
deleted file mode 100644
index ccf1ba1..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_0_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png
deleted file mode 100644
index 07937fe..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
deleted file mode 100644
index ba1b077..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png
deleted file mode 100644
index a705a89..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
deleted file mode 100644
index 0187d12..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png
deleted file mode 100644
index 0ed7d6f4..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
deleted file mode 100644
index 24a6e5a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png
deleted file mode 100644
index 1a47801..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
deleted file mode 100644
index d9648b6f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png
deleted file mode 100644
index 620da77..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png
deleted file mode 100644
index cf63e24..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png
deleted file mode 100644
index 8f68e1f..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png
deleted file mode 100644
index fa8735d..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png
deleted file mode 100644
index 894c63b..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_signal_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png
deleted file mode 100644
index 1ec5b49..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_in.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png
deleted file mode 100644
index 9ca3ca8..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_inout.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png
deleted file mode 100644
index 74241e0..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_out.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png
deleted file mode 100644
index 9553241..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png
deleted file mode 100644
index 4d70eb3..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png
deleted file mode 100644
index bfa3ad7..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_1_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png
deleted file mode 100644
index f7e78d07..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png
deleted file mode 100644
index fc90385..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_2_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png
deleted file mode 100644
index 931905e..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png
deleted file mode 100644
index f1fa45b..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_3_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png
deleted file mode 100644
index 0dd11a2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png
deleted file mode 100644
index 20991eb..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png
deleted file mode 100644
index de573b6..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_wifi_signal_null.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_zoom_default.png
deleted file mode 100644
index dd8c498..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_zoom_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_zoom_pressed.png
deleted file mode 100644
index dc42157..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/ic_sysbar_zoom_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_bg_protect_tile.png
deleted file mode 100644
index 59908ad..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_bg_protect_tile.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
deleted file mode 100644
index 03f4732..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
deleted file mode 100644
index 7bfdb46..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
deleted file mode 100644
index 4e20851..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
deleted file mode 100644
index 1c1b26b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/hd_off.png b/packages/SystemUI/res/drawable-xhdpi/hd_off.png
deleted file mode 100644
index 7f5bd88..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/hd_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/hd_on.png b/packages/SystemUI/res/drawable-xhdpi/hd_on.png
deleted file mode 100644
index 55305ce..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/hd_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_certificate_info.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_certificate_info.png
new file mode 100644
index 0000000..1bb2902
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_certificate_info.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
deleted file mode 100644
index 31ac35d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
deleted file mode 100644
index bc024da..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
deleted file mode 100644
index bbf5f7e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
deleted file mode 100644
index 35d85e1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
deleted file mode 100644
index bc1628f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
deleted file mode 100644
index 263c591..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
deleted file mode 100644
index 23d30fe..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
deleted file mode 100644
index 51b291c8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_expand_default.png
deleted file mode 100644
index 3abbe25..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_expand_default.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_expand_pressed.png
deleted file mode 100644
index 041eac5..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_expand_pressed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/hd.xml b/packages/SystemUI/res/drawable/hd.xml
deleted file mode 100644
index 73867a2..0000000
--- a/packages/SystemUI/res/drawable/hd.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_checked="false"
-          android:drawable="@drawable/hd_off" />
-    <item android:drawable="@drawable/hd_on" />
-</selector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_zoom.xml b/packages/SystemUI/res/drawable/ic_sysbar_zoom.xml
deleted file mode 100644
index 97d0348..0000000
--- a/packages/SystemUI/res/drawable/ic_sysbar_zoom.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_zoom_pressed" />
-    <item android:state_selected="true" android:drawable="@drawable/ic_sysbar_zoom_pressed" />
-    <item android:drawable="@drawable/ic_sysbar_zoom_default" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/stat_sys_gps_acquiring_anim.xml b/packages/SystemUI/res/drawable/stat_sys_gps_acquiring_anim.xml
deleted file mode 100644
index 393697c..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_gps_acquiring_anim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="false">
-    <item android:drawable="@drawable/stat_sys_gps_acquiring" android:duration="500" />
-    <item android:drawable="@*android:drawable/stat_sys_gps_on" android:duration="500" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/stat_sys_roaming_cdma_flash.xml b/packages/SystemUI/res/drawable/stat_sys_roaming_cdma_flash.xml
deleted file mode 100644
index 07dc446..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_roaming_cdma_flash.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/res/drawable/stat_sys_battery.xml
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="false">
-    <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim0" android:duration="800" />
-    <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim1" android:duration="1200" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/status_bar_expand.xml b/packages/SystemUI/res/drawable/status_bar_expand.xml
deleted file mode 100644
index f966920..0000000
--- a/packages/SystemUI/res/drawable/status_bar_expand.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/status_bar_expand_pressed" />
-    <item android:drawable="@drawable/status_bar_expand_default" />
-</selector>
-
diff --git a/packages/SystemUI/res/layout/compat_mode_help.xml b/packages/SystemUI/res/layout/compat_mode_help.xml
deleted file mode 100644
index 566d07d..0000000
--- a/packages/SystemUI/res/layout/compat_mode_help.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2011, 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.
-*/
--->
-
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent"
-    android:background="@drawable/compat_mode_help_bg"
-    >
-    <TextView
-        android:id="@+id/header"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="80dp"
-        android:layout_marginTop="80dp"
-        android:layout_marginEnd="80dp"
-        android:textSize="60sp"
-        android:maxLines="1"
-        android:shadowRadius="8"
-        android:shadowColor="#FF000000"
-        android:text="@string/compat_mode_help_header"
-        android:background="@drawable/compat_mode_help_divider_top"
-        />
-    <ImageView
-        android:id="@+id/diagram"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerInParent="true"
-        android:src="@drawable/compat_mode_help_diagram"
-        android:contentDescription="@string/accessibility_compatibility_zoom_example"
-        />
-    <RelativeLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="190dp"
-        android:background="@drawable/compat_mode_help_divider_bottom"
-        android:layout_marginBottom="55dp"
-        android:layout_marginEnd="80dp"
-        android:layout_alignStart="@id/header"
-        android:layout_alignParentBottom="true"
-        >
-        <ImageView
-            android:id="@+id/icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentEnd="true"
-            android:layout_centerVertical="true"
-            android:src="@drawable/compat_mode_help_icon"
-            android:contentDescription="@string/accessibility_compatibility_zoom_button"
-            />
-        <TextView
-            android:id="@+id/explanation"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_centerVertical="true"
-            android:layout_alignParentStart="true"
-            android:layout_toStartOf="@id/icon"
-            android:layout_marginEnd="10dp"
-            android:shadowRadius="4"
-            android:shadowColor="#FF000000"
-            android:textSize="28sp"
-            android:text="@string/compat_mode_help_body"
-            />
-    </RelativeLayout>
-    <Button
-        android:id="@+id/button"
-        android:layout_width="208dp"
-        android:layout_height="48dp"
-        android:layout_alignStart="@id/header"
-        android:layout_alignParentBottom="true"
-        android:layout_marginBottom="20dp"
-        android:textSize="28sp"
-        android:text="@android:string/ok"
-        />
-</RelativeLayout>
-
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c849aa6..8e88610 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -160,12 +160,6 @@
          [CHAR LIMIT=25] -->
     <string name="compat_mode_off">Stretch to fill screen</string>
 
-    <!-- Compatibility mode help screen: header text. [CHAR LIMIT=50] -->
-    <string name="compat_mode_help_header">Compatibility zoom</string>
-
-    <!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] -->
-    <string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string>
-
     <!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] -->
     <string name="screenshot_saving_ticker">Saving screenshot\u2026</string>
     <!-- Notification title displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=50] -->
@@ -506,4 +500,20 @@
 
     <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
     <string name="battery_meter_very_low_overlay_symbol">!</string>
+
+    <!-- Shows up when there is a user SSL CA Cert installed on the
+         device.  Indicates to the user that SSL traffic can be intercepted.  [CHAR LIMIT=NONE] -->
+    <string name="ssl_ca_cert_warning">Network may be monitored</string>
+    <!-- Button to close the SSL CA cert warning dialog box.  [CHAR LIMIT=NONE] -->
+    <string name="done_button">Done</string>
+    <!-- Title of Dialog warning users of SSL monitoring. [CHAR LIMIT=NONE] -->
+    <string name="ssl_ca_cert_dialog_title">Network Monitoring</string>
+    <!-- Text of message to show to users whose administrator has installed a SSL CA Cert.
+         [CHAR LIMIT=NONE] -->
+    <string name="ssl_ca_cert_info_message">This device is managed by: <xliff:g id="managing_domain">%s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity, including emails, apps, and secure websites.\n\nFor more information,contact your administrator.</string>
+    <!-- Text of warning to show to users that have a SSL CA Cert installed.  [CHAR LIMIT=NONE] -->
+    <string name="ssl_ca_cert_warning_message">A third party is capable of monitoring your network\nactivity, including emails, apps, and secure websites.\n\nA trusted credential installed on your device is making this possible.</string>
+    <!-- Label on button that will take the user to the Trusted Credentials settings page.
+         [CHAR LIMIT=NONE]-->
+    <string name="ssl_ca_cert_settings_button">Check trusted credentials</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2786867..a3b492c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -348,7 +348,8 @@
 
     protected View updateNotificationVetoButton(View row, StatusBarNotification n) {
         View vetoButton = row.findViewById(R.id.veto);
-        if (n.isClearable()) {
+        if (n.isClearable() || (mInterruptingNotificationEntry != null
+                && mInterruptingNotificationEntry.row == row)) {
             final String _pkg = n.getPackageName();
             final String _tag = n.getTag();
             final int _id = n.getId();
@@ -437,7 +438,6 @@
     }
 
     public void onHeadsUpDismissed() {
-        // pass
     }
 
     @Override
@@ -958,20 +958,20 @@
             if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
             oldEntry.notification = notification;
             try {
-                // Reapply the RemoteViews
-                contentView.reapply(mContext, oldEntry.expanded, mOnClickHandler);
-                if (bigContentView != null && oldEntry.getBigContentView() != null) {
-                    bigContentView.reapply(mContext, oldEntry.getBigContentView(), mOnClickHandler);
+                updateNotificationViews(oldEntry, notification);
+
+                if (ENABLE_HEADS_UP && mInterruptingNotificationEntry != null
+                        && oldNotification == mInterruptingNotificationEntry.notification) {
+                    if (!shouldInterrupt(notification)) {
+                        if (DEBUG) Log.d(TAG, "no longer interrupts!");
+                        mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
+                    } else {
+                        if (DEBUG) Log.d(TAG, "updating the current heads up:" + notification);
+                        mInterruptingNotificationEntry.notification = notification;
+                        updateNotificationViews(mInterruptingNotificationEntry, notification);
+                    }
                 }
-                // update the contentIntent
-                final PendingIntent contentIntent = notification.getNotification().contentIntent;
-                if (contentIntent != null) {
-                    final View.OnClickListener listener = makeClicker(contentIntent,
-                            notification.getPackageName(), notification.getTag(), notification.getId());
-                    oldEntry.content.setOnClickListener(listener);
-                } else {
-                    oldEntry.content.setOnClickListener(null);
-                }
+
                 // Update the icon.
                 final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(),
                         notification.getUser(),
@@ -997,7 +997,7 @@
             if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
             final boolean wasExpanded = oldEntry.row.isUserExpanded();
             removeNotificationViews(key);
-            addNotificationViews(key, notification);
+            addNotificationViews(key, notification);  // will also replace the heads up
             if (wasExpanded) {
                 final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
                 newEntry.row.setExpanded(true);
@@ -1022,17 +1022,25 @@
         // Recalculate the position of the sliding windows and the titles.
         setAreThereNotifications();
         updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+    }
 
-        // See if we need to update the heads up.
-        if (ENABLE_HEADS_UP && mInterruptingNotificationEntry != null
-                && oldNotification == mInterruptingNotificationEntry.notification) {
-            if (DEBUG) Log.d(TAG, "updating the current heads up:" + notification);
-            // XXX: this is a hack for Alarms. The real implementation will need to *update*
-            // the heads up.
-            if (!shouldInterrupt(notification)) {
-                if (DEBUG) Log.d(TAG, "no longer interrupts!");
-                mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
-            }
+    private void updateNotificationViews(NotificationData.Entry entry,
+            StatusBarNotification notification) {
+        final RemoteViews contentView = notification.getNotification().contentView;
+        final RemoteViews bigContentView = notification.getNotification().bigContentView;
+        // Reapply the RemoteViews
+        contentView.reapply(mContext, entry.expanded, mOnClickHandler);
+        if (bigContentView != null && entry.getBigContentView() != null) {
+            bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler);
+        }
+        // update the contentIntent
+        final PendingIntent contentIntent = notification.getNotification().contentIntent;
+        if (contentIntent != null) {
+            final View.OnClickListener listener = makeClicker(contentIntent,
+                    notification.getPackageName(), notification.getTag(), notification.getId());
+            entry.content.setOnClickListener(listener);
+        } else {
+            entry.content.setOnClickListener(null);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 53041b7..e8173b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -236,7 +236,7 @@
 
     public void setWindowState(int window, int state) {
         synchronized (mList) {
-            mHandler.removeMessages(MSG_SET_WINDOW_STATE);
+            // don't coalesce these
             mHandler.obtainMessage(MSG_SET_WINDOW_STATE, window, state, null).sendToTarget();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index e40c4e5..292ea7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -37,12 +37,13 @@
     public static final int MODE_TRANSPARENT = 2;
 
     private final String mTag;
-    private final View mTarget;
-    private final int mOpaque;
-    private final int mSemiTransparent;
+    protected final View mTarget;
+    protected final int mOpaque;
+    protected final int mSemiTransparent;
 
     protected Drawable mTransparent;
     private int mMode;
+    private ValueAnimator mBackgroundColorAnimator;
 
     private final AnimatorUpdateListener mBackgroundColorListener = new AnimatorUpdateListener() {
         @Override
@@ -80,10 +81,11 @@
     }
 
     protected void onTransition(int oldMode, int newMode, boolean animate) {
+        cancelBackgroundColorAnimation();
         if (animate && oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE) {
-            startColorAnimation(mSemiTransparent, mOpaque);
+            startBackgroundColorAnimation(mSemiTransparent, mOpaque);
         } else if (animate && oldMode == MODE_OPAQUE && newMode == MODE_SEMI_TRANSPARENT) {
-            startColorAnimation(mOpaque, mSemiTransparent);
+            startBackgroundColorAnimation(mOpaque, mSemiTransparent);
         } else if (newMode == MODE_OPAQUE || newMode == MODE_SEMI_TRANSPARENT) {
             mTarget.setBackgroundColor(newMode == MODE_OPAQUE ? mOpaque : mSemiTransparent);
         } else {
@@ -93,10 +95,17 @@
         }
     }
 
-    private void startColorAnimation(int from, int to) {
-        ValueAnimator anim = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
-        anim.addUpdateListener(mBackgroundColorListener);
-        anim.start();
+    private void startBackgroundColorAnimation(int from, int to) {
+        mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
+        mBackgroundColorAnimator.addUpdateListener(mBackgroundColorListener);
+        mBackgroundColorAnimator.start();
+    }
+
+    private void cancelBackgroundColorAnimation() {
+        if (mBackgroundColorAnimator != null && mBackgroundColorAnimator.isStarted()) {
+            mBackgroundColorAnimator.cancel();
+            mBackgroundColorAnimator = null;
+        }
     }
 
     public static String modeToString(int mode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index ad53fea3..02346d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -104,7 +104,7 @@
 public class PhoneStatusBar extends BaseStatusBar {
     static final String TAG = "PhoneStatusBar";
     public static final boolean DEBUG = BaseStatusBar.DEBUG;
-    public static final boolean SPEW = DEBUG;
+    public static final boolean SPEW = false;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
     public static final boolean DEBUG_GESTURES = false;
 
@@ -911,9 +911,9 @@
 
     @Override
     public void resetHeadsUpDecayTimer() {
-        mHandler.removeMessages(MSG_HIDE_HEADS_UP);
         if (mUseHeadsUp && mHeadsUpNotificationDecay > 0
-                && !mHeadsUpNotificationView.isInsistent()) {
+                && mHeadsUpNotificationView.isClearable()) {
+            mHandler.removeMessages(MSG_HIDE_HEADS_UP);
             mHandler.sendEmptyMessageDelayed(MSG_HIDE_HEADS_UP, mHeadsUpNotificationDecay);
         }
     }
@@ -1066,7 +1066,7 @@
         if (!mShowCarrierInPanel) return;
         // The idea here is to only show the carrier label when there is enough room to see it,
         // i.e. when there aren't enough notifications to fill the panel.
-        if (DEBUG) {
+        if (SPEW) {
             Log.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d",
                     mPile.getHeight(), mScrollView.getHeight(), mCarrierLabelHeight));
         }
@@ -1110,7 +1110,7 @@
 
         final boolean clearable = any && mNotificationData.hasClearableItems();
 
-        if (DEBUG) {
+        if (SPEW) {
             Log.d(TAG, "setAreThereNotifications: N=" + mNotificationData.size()
                     + " any=" + any + " clearable=" + clearable);
         }
@@ -1319,12 +1319,10 @@
                     break;
                 case MSG_HIDE_HEADS_UP:
                     setHeadsUpVisibility(false);
-                    mInterruptingNotificationEntry = null;
                     break;
                 case MSG_ESCALATE_HEADS_UP:
                     escalateHeadsUp();
                     setHeadsUpVisibility(false);
-                    mInterruptingNotificationEntry = null;
                     break;
             }
         }
@@ -1841,37 +1839,26 @@
 
     @Override // CommandQueue
     public void setWindowState(int window, int state) {
+        boolean showing = state == StatusBarManager.WINDOW_STATE_SHOWING;
         if (mStatusBarWindow != null
                 && window == StatusBarManager.WINDOW_STATUS_BAR
                 && mStatusBarWindowState != state) {
             mStatusBarWindowState = state;
-            if (DEBUG) Log.d(TAG, "Status bar window " + stateString(state));
-            if (state == StatusBarManager.WINDOW_STATE_HIDING) {
-                mStatusBarWindow.setEnabled(false);
+            if (DEBUG) Log.d(TAG, "Status bar " + StatusBarManager.windowStateToString(state));
+            mStatusBarWindow.setEnabled(showing);
+            if (!showing) {
                 mStatusBarView.collapseAllPanels(false);
-            } else if (state == StatusBarManager.WINDOW_STATE_SHOWING) {
-                mStatusBarWindow.setEnabled(true);
             }
         }
         if (mNavigationBarView != null
                 && window == StatusBarManager.WINDOW_NAVIGATION_BAR
                 && mNavigationBarWindowState != state) {
             mNavigationBarWindowState = state;
-            if (DEBUG) Log.d(TAG, "Navigation bar window " + stateString(state));
-            if (state == StatusBarManager.WINDOW_STATE_HIDING) {
-                mNavigationBarView.setEnabled(false);
-            } else if (state == StatusBarManager.WINDOW_STATE_SHOWING) {
-                mNavigationBarView.setEnabled(true);
-            }
+            if (DEBUG) Log.d(TAG, "Navigation bar " + StatusBarManager.windowStateToString(state));
+            mNavigationBarView.setEnabled(showing);
         }
     }
 
-    private static String stateString(int state) {
-        if (state == StatusBarManager.WINDOW_STATE_HIDING) return "hiding";
-        if (state == StatusBarManager.WINDOW_STATE_SHOWING) return "showing";
-        return "unknown";
-    }
-
     @Override // CommandQueue
     public void setSystemUiVisibility(int vis, int mask) {
         final int oldVal = mSystemUiVisibility;
@@ -1904,11 +1891,13 @@
 
             // update status bar mode
             int sbMode = updateBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),
-                    View.STATUS_BAR_TRANSIENT, View.SYSTEM_UI_FLAG_TRANSPARENT_STATUS);
+                    View.STATUS_BAR_TRANSIENT, View.SYSTEM_UI_FLAG_TRANSPARENT_STATUS,
+                    mStatusBarWindowState);
 
             // update navigation bar mode
             int nbMode = updateBarMode(oldVal, newVal, mNavigationBarView.getBarTransitions(),
-                    View.NAVIGATION_BAR_TRANSIENT, View.SYSTEM_UI_FLAG_TRANSPARENT_NAVIGATION);
+                    View.NAVIGATION_BAR_TRANSIENT, View.SYSTEM_UI_FLAG_TRANSPARENT_NAVIGATION,
+                    mNavigationBarWindowState);
 
             if (sbMode != -1 || nbMode != -1) {
                 // update transient bar autohide
@@ -1919,19 +1908,29 @@
                 }
             }
 
+            // ready to unhide
+            if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
+                mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
+            }
+            if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
+                mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
+            }
+
             // send updated sysui visibility to window manager
             notifyUiVisibilityChanged(mSystemUiVisibility);
         }
     }
 
     private int updateBarMode(int oldVis, int newVis, BarTransitions transitions,
-            int transientFlag, int transparentFlag) {
+            int transientFlag, int transparentFlag, int windowState) {
         final int oldMode = barMode(oldVis, transientFlag, transparentFlag);
         final int newMode = barMode(newVis, transientFlag, transparentFlag);
         if (oldMode == newMode) {
             return -1; // no mode change
         }
-        transitions.transitionTo(newMode);
+        boolean animate = windowState == StatusBarManager.WINDOW_STATE_SHOWING
+                && oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE;
+        transitions.transitionTo(newMode, animate);
         return newMode;
     }
 
@@ -1941,11 +1940,19 @@
                 : MODE_OPAQUE;
     }
 
+    private final Runnable mResumeSemiTransparent = new Runnable() {
+        @Override
+        public void run() {
+            if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0) {
+                animateTransitionTo(BarTransitions.MODE_SEMI_TRANSPARENT);
+            }
+        }};
+
     @Override
     public void resumeAutohide() {
         if (mAutohideSuspended) {
             scheduleAutohide();
-            animateTransitionTo(BarTransitions.MODE_SEMI_TRANSPARENT);
+            mHandler.postDelayed(mResumeSemiTransparent, 500); // longer than home -> launcher
         }
     }
 
@@ -1959,7 +1966,8 @@
     @Override
     public void suspendAutohide() {
         mHandler.removeCallbacks(mAutohide);
-        mAutohideSuspended = 0 != (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT);
+        mHandler.removeCallbacks(mResumeSemiTransparent);
+        mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0;
         animateTransitionTo(BarTransitions.MODE_OPAQUE);
     }
 
@@ -1984,7 +1992,7 @@
 
     private void userAutohide() {
         cancelAutohide();
-        mHandler.postDelayed(mAutohide, 25);
+        mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear
     }
 
     private void setStatusBarLowProfile(boolean lightsOut) {
@@ -2287,7 +2295,7 @@
 
     @Override
     public void updateExpandedViewPos(int thingy) {
-        if (DEBUG) Log.v(TAG, "updateExpandedViewPos");
+        if (SPEW) Log.v(TAG, "updateExpandedViewPos");
 
         // on larger devices, the notification panel is propped open a bit
         mNotificationPanel.setMinimumHeight(
@@ -2497,6 +2505,10 @@
         if (!ENABLE_HEADS_UP) return;
         if (DEBUG) Log.v(TAG, (vis ? "showing" : "hiding") + " heads up window");
         mHeadsUpNotificationView.setVisibility(vis ? View.VISIBLE : View.GONE);
+        if (!vis) {
+            if (DEBUG) Log.d(TAG, "setting heads up entry to null");
+            mInterruptingNotificationEntry = null;
+        }
     }
 
     public void animateHeadsUp(boolean animateInto, float frac) {
@@ -2512,14 +2524,16 @@
 
     public void onHeadsUpDismissed() {
         if (mInterruptingNotificationEntry == null) return;
-
-        try {
-            mBarService.onNotificationClear(
-                    mInterruptingNotificationEntry.notification.getPackageName(),
-                    mInterruptingNotificationEntry.notification.getTag(),
-                    mInterruptingNotificationEntry.notification.getId());
-        } catch (android.os.RemoteException ex) {
-            // oh well
+        mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
+        if (mHeadsUpNotificationView.isClearable()) {
+            try {
+                mBarService.onNotificationClear(
+                        mInterruptingNotificationEntry.notification.getPackageName(),
+                        mInterruptingNotificationEntry.notification.getTag(),
+                        mInterruptingNotificationEntry.notification.getId());
+            } catch (android.os.RemoteException ex) {
+                // oh well
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 5f034a8c..b9c6fef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -20,6 +20,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -49,6 +50,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Profile;
 import android.provider.Settings;
+import android.security.KeyChain;
 import android.util.Log;
 import android.util.Pair;
 import android.view.LayoutInflater;
@@ -89,6 +91,7 @@
     private ViewGroup mContainerView;
 
     private DisplayManager mDisplayManager;
+    private DevicePolicyManager mDevicePolicyManager;
     private WifiDisplayStatus mWifiDisplayStatus;
     private PhoneStatusBar mStatusBarService;
     private BluetoothState mBluetoothState;
@@ -100,6 +103,7 @@
     private LocationController mLocationController;
 
     private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
+    private AsyncTask<Void, Void, Pair<Boolean, Boolean>> mQueryCertTask;
 
     private LevelListDrawable mBatteryLevels;
     private LevelListDrawable mChargingBatteryLevels;
@@ -116,6 +120,8 @@
 
     public QuickSettings(Context context, QuickSettingsContainerView container) {
         mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+        mDevicePolicyManager
+            = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
         mContext = context;
         mContainerView = container;
         mModel = new QuickSettingsModel(context);
@@ -137,6 +143,7 @@
         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
         mContext.registerReceiver(mReceiver, filter);
 
         IntentFilter profileFilter = new IntentFilter();
@@ -181,6 +188,26 @@
         rotationLockController.addRotationLockControllerCallback(mModel);
     }
 
+    private void queryForSslCaCerts() {
+        mQueryCertTask = new AsyncTask<Void, Void, Pair<Boolean, Boolean>>() {
+            @Override
+            protected Pair<Boolean, Boolean> doInBackground(Void... params) {
+                boolean hasCert = mDevicePolicyManager.hasAnyCaCertsInstalled();
+                boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
+
+                return Pair.create(hasCert, isManaged);
+            }
+            @Override
+            protected void onPostExecute(Pair<Boolean, Boolean> result) {
+                super.onPostExecute(result);
+                boolean hasCert = result.first;
+                boolean isManaged = result.second;
+                mModel.setSslCaCertWarningTileInfo(hasCert, isManaged);
+            }
+        };
+        mQueryCertTask.execute();
+    }
+
     private void queryForUserInformation() {
         Context currentUserContext = null;
         UserInfo userInfo = null;
@@ -254,6 +281,7 @@
         addTemporaryTiles(mContainerView, inflater);
 
         queryForUserInformation();
+        queryForSslCaCerts();
         mTilesSetUp = true;
     }
 
@@ -721,6 +749,25 @@
         });
         parent.addView(imeTile);
         */
+
+        // SSL CA Cert Warning.
+        final QuickSettingsBasicTile sslCaCertWarningTile = new QuickSettingsBasicTile(mContext);
+        sslCaCertWarningTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                collapsePanels();
+                showSslCaCertWarningDialog();
+            }
+        });
+
+        sslCaCertWarningTile.setImageResource(
+                com.android.internal.R.drawable.indicator_input_error);
+        sslCaCertWarningTile.setTextResource(R.string.ssl_ca_cert_warning);
+
+        mModel.addSslCaCertWarningTile(sslCaCertWarningTile,
+                new QuickSettingsModel.BasicRefreshCallback(sslCaCertWarningTile)
+                        .setShowWhenEnabled(true));
+        parent.addView(sslCaCertWarningTile);
     }
 
     void updateResources() {
@@ -777,6 +824,45 @@
         dialog.show();
     }
 
+    private void showSslCaCertWarningDialog() {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+        builder.setTitle(R.string.ssl_ca_cert_dialog_title);
+        builder.setCancelable(true);
+        final boolean hasDeviceOwner = mDevicePolicyManager.getDeviceOwner() != null;
+        int buttonLabel;
+        if (hasDeviceOwner) {
+            // Institutional case.  Show informational message.
+            String message = mContext.getResources().getString(R.string.ssl_ca_cert_info_message,
+                    mDevicePolicyManager.getDeviceOwnerName());
+            builder.setMessage(message);
+            buttonLabel = R.string.done_button;
+        } else {
+            // Consumer case.  Show scary warning.
+            builder.setMessage(R.string.ssl_ca_cert_warning_message);
+            buttonLabel = R.string.ssl_ca_cert_settings_button;
+        }
+
+        builder.setPositiveButton(buttonLabel, new OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                // do something.
+                if (hasDeviceOwner) {
+                    // Close
+                } else {
+                    startSettingsActivity("com.android.settings.TRUSTED_CREDENTIALS_USER");
+                }
+            }
+        });
+
+        final Dialog dialog = builder.create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        try {
+            WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
+        } catch (RemoteException e) {
+        }
+        dialog.show();
+    }
+
     private void updateWifiDisplayStatus() {
         mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
         applyWifiDisplayStatus();
@@ -801,6 +887,7 @@
         }
         if (mTilesSetUp) {
             queryForUserInformation();
+            queryForSslCaCerts();
         }
     }
 
@@ -829,6 +916,8 @@
                 if (mUseDefaultAvatar) {
                     queryForUserInformation();
                 }
+            } else if (KeyChain.ACTION_STORAGE_CHANGED.equals(action)) {
+                queryForSslCaCerts();
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 02a3690..98e480a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -263,6 +263,10 @@
     private RefreshCallback mSettingsCallback;
     private State mSettingsState = new State();
 
+    private QuickSettingsTileView mSslCaCertWarningTile;
+    private RefreshCallback mSslCaCertWarningCallback;
+    private State mSslCaCertWarningState = new State();
+
     private RotationLockController mRotationLockController;
 
     public QuickSettingsModel(Context context) {
@@ -747,4 +751,23 @@
     void refreshBrightnessTile() {
         onBrightnessLevelChanged();
     }
+
+    // SSL CA Cert warning.
+    public void addSslCaCertWarningTile(QuickSettingsTileView view, RefreshCallback cb) {
+        mSslCaCertWarningTile = view;
+        mSslCaCertWarningCallback = cb;
+        // Set a sane default while we wait for the AsyncTask to finish (no cert).
+        setSslCaCertWarningTileInfo(false, true);
+    }
+    public void setSslCaCertWarningTileInfo(boolean hasCert, boolean isManaged) {
+        Resources r = mContext.getResources();
+        mSslCaCertWarningState.enabled = hasCert;
+        if (isManaged) {
+            mSslCaCertWarningState.iconId = R.drawable.ic_qs_certificate_info;
+        } else {
+            mSslCaCertWarningState.iconId = android.R.drawable.stat_notify_error;
+        }
+        mSslCaCertWarningState.label = r.getString(R.string.ssl_ca_cert_warning);
+        mSslCaCertWarningCallback.refreshView(mSslCaCertWarningTile, mSslCaCertWarningState);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index da90fd1..f1fda78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -38,6 +38,7 @@
 public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.Callback, ExpandHelper.Callback {
     private static final String TAG = "HeadsUpNotificationView";
     private static final boolean DEBUG = false;
+    private static final boolean SPEW = DEBUG;
 
     Rect mTmpRect = new Rect();
 
@@ -88,13 +89,12 @@
         return true;
     }
 
-    public boolean isInsistent() {
-        return mHeadsUp != null
-                && (mHeadsUp.notification.getNotification().flags & Notification.FLAG_INSISTENT) != 0;
+    public boolean isClearable() {
+        return mHeadsUp == null || mHeadsUp.notification.isClearable();
     }
 
     public void setMargin(int notificationPanelMarginPx) {
-        if (DEBUG) Log.v(TAG, "setMargin() " + notificationPanelMarginPx);
+        if (SPEW) Log.v(TAG, "setMargin() " + notificationPanelMarginPx);
         if (mContentSlider != null) {
             FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentSlider.getLayoutParams();
             lp.setMarginStart(notificationPanelMarginPx);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index c2ffff8f..7455628 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -123,15 +123,17 @@
         final ContentResolver cr = mContext.getContentResolver();
         // When enabling location, a user consent dialog will pop up, and the
         // setting won't be fully enabled until the user accepts the agreement.
-        Settings.Secure.setLocationMasterSwitchEnabled(cr, enabled);
+        int mode = enabled
+                ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY : Settings.Secure.LOCATION_MODE_OFF;
+        Settings.Secure.setLocationMode(cr, mode);
     }
 
     /**
-     * Returns true if either gps or network location are enabled in settings.
+     * Returns true if location isn't disabled in settings.
      */
     public boolean isLocationEnabled() {
-        ContentResolver contentResolver = mContext.getContentResolver();
-        return Settings.Secure.isLocationMasterSwitchEnabled(contentResolver);
+        ContentResolver resolver = mContext.getContentResolver();
+        return Settings.Secure.getLocationMode(resolver) != Settings.Secure.LOCATION_MODE_OFF;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index fb2348e..34e3013 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -430,7 +430,8 @@
         @Override
         public void onServiceStateChanged(ServiceState state) {
             if (DEBUG) {
-                Log.d(TAG, "onServiceStateChanged state=" + state.getState());
+                Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
+                        + " dataState=" + state.getDataRegState());
             }
             mServiceState = state;
             updateTelephonySignalStrength();
@@ -506,10 +507,16 @@
 
     private boolean hasService() {
         if (mServiceState != null) {
-            switch (mServiceState.getState()) {
-                case ServiceState.STATE_OUT_OF_SERVICE:
+            // Consider the device to be in service if either voice or data service is available.
+            // Some SIM cards are marketed as data-only and do not support voice service, and on
+            // these SIM cards, we want to show signal bars for data service as well as the "no
+            // service" or "emergency calls only" text that indicates that voice is not available.
+            switch(mServiceState.getVoiceRegState()) {
                 case ServiceState.STATE_POWER_OFF:
                     return false;
+                case ServiceState.STATE_OUT_OF_SERVICE:
+                case ServiceState.STATE_EMERGENCY_ONLY:
+                    return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
                 default:
                     return true;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
index 16a92ea..73979a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
@@ -22,7 +22,6 @@
 public class Prefs {
     private static final String SHARED_PREFS_NAME = "status_bar";
 
-    public static final String SHOWN_COMPAT_MODE_HELP = "shown_compat_mode_help";
     public static final String SHOWN_QUICK_SETTINGS_HELP = "shown_quick_settings_help";
 
     public static SharedPreferences read(Context context) {
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index e4afde6..d9566d5 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -18,24 +18,15 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := \
-    main_pacserver.cpp \
-    ProxyService.cpp \
-    IProxyService.cpp
-
-LOCAL_C_INCLUDES += \
-    external/chromium-libpac/src
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils \
-    liblog \
-    libpac \
-    libbinder \
-    libstlport
-
-LOCAL_MODULE := pacserver
 LOCAL_MODULE_TAGS := optional
 
-include external/stlport/libstlport.mk
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-include $(BUILD_EXECUTABLE)
+LOCAL_PACKAGE_NAME := PacProcessor
+LOCAL_CERTIFICATE := platform
+
+LOCAL_REQUIRED_MODULES := libjni_pacprocessor
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/services/PacProcessor/AndroidManifest.xml b/packages/services/PacProcessor/AndroidManifest.xml
new file mode 100644
index 0000000..6740c16
--- /dev/null
+++ b/packages/services/PacProcessor/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.pacprocessor">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+        android:label="@string/app_name">
+
+        <service android:name=".PacService"
+            android:exported="true">
+        </service>
+
+    </application>
+
+</manifest>
diff --git a/packages/services/PacProcessor/IProxyService.cpp b/packages/services/PacProcessor/IProxyService.cpp
deleted file mode 100644
index 3707d85..0000000
--- a/packages/services/PacProcessor/IProxyService.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-#define LOG_TAG "ProxyTesting"
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <utils/Errors.h>
-#include "IProxyService.h"
-
-#include <utils/Log.h>
-
-#include <private/android_filesystem_config.h>
-
-using namespace android;
-
-String16 BpProxyService::resolveProxies(String16 host, String16 url) {
-    String16 ret;
-    return ret;
-}
-
-void BpProxyService::setPacFile(String16& scriptContents) {
-
-}
-
-void BpProxyService::startPacSystem() {
-
-}
-void BpProxyService::stopPacSystem() {
-
-}
-
-IMPLEMENT_META_INTERFACE(ProxyService, "com.android.net.IProxyService");
-
-status_t BnProxyService::onTransact(
-            uint32_t code, const Parcel& data,
-            Parcel* reply, uint32_t flags) {
-    int returnInt = 0;
-    switch (code) {
-    case RESOLVE_PROXIES:
-    {
-        CHECK_INTERFACE(IProxyService, data, reply);
-        String16 host = data.readString16();
-        String16 url = data.readString16();
-        String16 response = resolveProxies(host, url);
-        reply->writeNoException();
-        reply->writeString16(response);
-        return NO_ERROR;
-    } break;
-    case SET_PAC:
-    {
-        CHECK_INTERFACE(IProxyService, data, reply);
-        if (notSystemUid()) {
-            returnInt = 1;
-        } else {
-            String16 pacFile = data.readString16();
-            setPacFile(pacFile);
-        }
-        reply->writeNoException();
-        reply->writeInt32(returnInt);
-        return NO_ERROR;
-    } break;
-    case START_PAC:
-    {
-        CHECK_INTERFACE(IProxyService, data, reply);
-        if (notSystemUid()) {
-            returnInt = 1;
-        } else {
-            startPacSystem();
-        }
-        reply->writeNoException();
-        reply->writeInt32(returnInt);
-        return NO_ERROR;
-    } break;
-    case STOP_PAC:
-    {
-        CHECK_INTERFACE(IProxyService, data, reply);
-        if (notSystemUid()) {
-            returnInt = 1;
-        } else {
-            stopPacSystem();
-        }
-        reply->writeNoException();
-        reply->writeInt32(returnInt);
-        return NO_ERROR;
-    } break;
-    default:
-        return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-int BnProxyService::getCallingUid() {
-    return IPCThreadState::self()->getCallingUid();
-}
-
-bool BnProxyService::notSystemUid() {
-    return getCallingUid() != AID_SYSTEM;
-}
diff --git a/packages/services/PacProcessor/IProxyService.h b/packages/services/PacProcessor/IProxyService.h
deleted file mode 100644
index 57c527b..0000000
--- a/packages/services/PacProcessor/IProxyService.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef IPROXY_SERVICE_H
-#define IPROXY_SERVICE_H
-
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
-
-namespace android {
-class IProxyService : public IInterface {
-public:
-    /**
-     * Keep up-to-date with
-     * frameworks/base/packages/services/Proxy/com/android/net/IProxyService.aidl
-     */
-    enum {
-        RESOLVE_PROXIES = IBinder::FIRST_CALL_TRANSACTION,
-        SET_PAC,
-        START_PAC,
-        STOP_PAC,
-    };
-public:
-    DECLARE_META_INTERFACE(ProxyService);
-
-public:
-
-    virtual String16 resolveProxies(String16 host, String16 url) = 0;
-
-    virtual void setPacFile(String16& scriptContents) = 0;
-
-    virtual void startPacSystem() = 0;
-    virtual void stopPacSystem() = 0;
-private:
-};
-
-class BpProxyService : public BpInterface<IProxyService> {
-public:
-    BpProxyService(const sp<IBinder>& impl) : BpInterface<IProxyService>(impl) {}
-
-    virtual String16 resolveProxies(String16 host, String16 url);
-
-    virtual void setPacFile(String16& scriptContents);
-
-    virtual void startPacSystem();
-    virtual void stopPacSystem();
-};
-
-class BnProxyService : public BnInterface<IProxyService> {
-public:
-    virtual status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
-
-private:
-    int getCallingUid();
-
-    bool notSystemUid();
-};
-}
-
-
-#endif //IPROXY_SERVICE_H
diff --git a/packages/services/PacProcessor/ProxyService.cpp b/packages/services/PacProcessor/ProxyService.cpp
deleted file mode 100644
index 7084a47..0000000
--- a/packages/services/PacProcessor/ProxyService.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#define LOG_TAG "ProxyService"
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <utils/threads.h>
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <sys/stat.h>
-#include <proxy_resolver_v8.h>
-#include <sstream>
-
-#include "ProxyService.h"
-
-using namespace net;
-
-using namespace android;
-
-class ProxyErrorLogger : public ProxyErrorListener {
-protected:
-    ~ProxyErrorLogger() {
-
-    }
-public:
-    void AlertMessage(String16 message) {
-        String8 str(message);
-        ALOGD("Alert: %s", str.string());
-    }
-    void ErrorMessage(String16 message) {
-        String8 str(message);
-        ALOGE("Error: %s", str.string());
-    }
-};
-
-void ProxyService::instantiate() {
-    ALOGV("instantiate");
-    defaultServiceManager()->addService(String16("com.android.net.IProxyService"),
-            new ProxyService());
-}
-
-ProxyService::ProxyService() {
-    hasSetScript = false;
-}
-
-ProxyService::~ProxyService() {
-    stopPacSystem();
-}
-
-String16 ProxyService::resolveProxies(String16 host, String16 url) {
-    ALOGV("resolve");
-    String16 blankRet;
-    if (proxyResolver != NULL) {
-        if (hasSetScript) {
-            String16 ret;
-            if (proxyResolver->GetProxyForURL(url, host, &ret) != OK) {
-                return blankRet;
-            }
-            return ret;
-        } else {
-            ALOGD("Unable to resolve PAC when no script is set!");
-        }
-    } else {
-        ALOGE("Cannot parse while resolver not initialized!");
-    }
-    return blankRet;
-}
-
-void ProxyService::setPacFile(String16& scriptContents) {
-    ALOGV("set");
-    if (proxyResolver != NULL) {
-        if (proxyResolver->SetPacScript(scriptContents) != OK) {
-            ALOGD("Unable to initialize PAC - Resolving will not work");
-        } else {
-            hasSetScript = true;
-        }
-    } else {
-        ALOGE("PAC script set while resolver not initialized!");
-    }
-}
-
-void ProxyService::startPacSystem() {
-    ALOGV("start");
-    // Stop in case redundant start call
-    stopPacSystem();
-
-    proxyResolver = new ProxyResolverV8(ProxyResolverJSBindings::CreateDefault(),
-            new ProxyErrorLogger());
-    hasSetScript = false;
-}
-
-void ProxyService::stopPacSystem() {
-    ALOGV("stop");
-    if (proxyResolver != NULL) {
-        delete proxyResolver;
-        proxyResolver = NULL;
-    }
-}
diff --git a/packages/services/PacProcessor/ProxyService.h b/packages/services/PacProcessor/ProxyService.h
deleted file mode 100644
index a0861b2..0000000
--- a/packages/services/PacProcessor/ProxyService.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef PROXY_SERVICE_H
-#define PROXY_SERVICE_H
-
-#include <binder/IInterface.h>
-#include "IProxyService.h"
-#include "proxy_resolver_v8.h"
-
-namespace android {
-
-class ProxyService : public BnProxyService {
-public:
-    static void instantiate();
-
-private:
-    ProxyService();
-    virtual ~ProxyService();
-
-public:
-    String16 resolveProxies(String16 host, String16 url);
-
-    void setPacFile(String16& scriptContents);
-
-    void startPacSystem();
-    void stopPacSystem();
-
-private:
-    net::ProxyResolverV8* proxyResolver;
-    bool hasSetScript;
-};
-
-}
-
-#endif //PROXY_SERVICE_H
diff --git a/packages/services/PacProcessor/com/android/net/IProxyService.aidl b/packages/services/PacProcessor/com/android/net/IProxyService.aidl
new file mode 100644
index 0000000..4e54aba
--- /dev/null
+++ b/packages/services/PacProcessor/com/android/net/IProxyService.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.net;
+
+/** @hide */
+interface IProxyService
+{
+    String resolvePacFile(String host, String url);
+
+    oneway void setPacFile(String scriptContents);
+
+    oneway void startPacSystem();
+    oneway void stopPacSystem();
+}
diff --git a/packages/services/PacProcessor/jni/Android.mk b/packages/services/PacProcessor/jni/Android.mk
new file mode 100644
index 0000000..f16c90b
--- /dev/null
+++ b/packages/services/PacProcessor/jni/Android.mk
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    jni_init.cpp \
+    com_android_pacprocessor_PacNative.cpp
+
+LOCAL_C_INCLUDES += \
+    external/chromium-libpac/src
+
+LOCAL_SHARED_LIBRARIES := \
+    libandroidfw \
+    libandroid_runtime \
+    liblog \
+    libutils \
+    libnativehelper \
+    libpac
+
+LOCAL_MODULE := libjni_pacprocessor
+LOCAL_MODULE_TAGS := optional
+
+include external/stlport/libstlport.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
new file mode 100644
index 0000000..c5aa13b
--- /dev/null
+++ b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PacProcessor"
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include "android_runtime/AndroidRuntime.h"
+
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include "proxy_resolver_v8.h"
+
+namespace android {
+
+class ProxyErrorLogger : public net::ProxyErrorListener {
+public:
+    ~ProxyErrorLogger() {
+
+    }
+    void AlertMessage(String16 message) {
+        String8 str(message);
+        ALOGD("Alert: %s", str.string());
+    }
+    void ErrorMessage(String16 message) {
+        String8 str(message);
+        ALOGE("Error: %s", str.string());
+    }
+};
+
+net::ProxyResolverV8* proxyResolver = NULL;
+ProxyErrorLogger* logger = NULL;
+bool pacSet = false;
+
+String16 jstringToString16(JNIEnv* env, jstring jstr) {
+    const jchar* str = env->GetStringCritical(jstr, 0);
+    String16 str16(str, env->GetStringLength(jstr));
+    env->ReleaseStringCritical(jstr, str);
+    return str16;
+}
+
+jstring string16ToJstring(JNIEnv* env, String16 string) {
+    const char16_t* str = string.string();
+    size_t len = string.size();
+
+    return env->NewString(str, len);
+}
+
+static jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* env, 
+        jobject) {
+    if (proxyResolver == NULL) {
+        logger = new ProxyErrorLogger();
+        proxyResolver = new net::ProxyResolverV8(net::ProxyResolverJSBindings::CreateDefault(),
+                logger);
+        pacSet = false;
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+static jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* env, 
+        jobject) {
+    if (proxyResolver != NULL) {
+        delete logger;
+        delete proxyResolver;
+        logger = NULL;
+        proxyResolver = NULL;
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+static jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject,
+        jstring script) {
+    String16 script16 = jstringToString16(env, script);
+
+    if (proxyResolver == NULL) {
+        ALOGE("V8 Parser not started when setting PAC script");
+        return JNI_TRUE;
+    }
+
+    if (proxyResolver->SetPacScript(script16) != OK) {
+        ALOGE("Unable to set PAC script");
+        return JNI_TRUE;
+    }
+    pacSet = true;
+
+    return JNI_FALSE;
+}
+
+static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject,
+        jstring url, jstring host) {
+    String16 url16 = jstringToString16(env, url);
+    String16 host16 = jstringToString16(env, host);
+    String16 ret;
+
+    if (proxyResolver == NULL) {
+        ALOGE("V8 Parser not initialized when running PAC script");
+        return NULL;
+    }
+
+    if (!pacSet) {
+        ALOGW("Attempting to run PAC with no script set");
+        return NULL;
+    }
+
+    if (proxyResolver->GetProxyForURL(url16, host16, &ret) != OK) {
+        String8 ret8(ret);
+        ALOGE("Error Running PAC: %s", ret8.string());
+        return NULL;
+    }
+
+    jstring jret = string16ToJstring(env, ret);
+
+    return jret;
+}
+
+static JNINativeMethod gMethods[] = {
+    { "createV8ParserNativeLocked", "()Z",
+        (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
+    { "destroyV8ParserNativeLocked", "()Z",
+        (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked},
+    { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z",
+        (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked},
+    { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+        (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked},
+};
+
+int register_com_android_pacprocessor_PacNative(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative",
+            gMethods, NELEM(gMethods));
+}
+
+} /* namespace android */
diff --git a/packages/services/PacProcessor/jni/jni_init.cpp b/packages/services/PacProcessor/jni/jni_init.cpp
new file mode 100644
index 0000000..bda33fb
--- /dev/null
+++ b/packages/services/PacProcessor/jni/jni_init.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PacProcessor"
+
+#include <utils/Log.h>
+#include "jni.h"
+
+namespace android {
+    extern int register_com_android_pacprocessor_PacNative(JNIEnv *env);
+}
+
+using namespace android;
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+    JNIEnv *env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("ERROR: GetEnv failed");
+        return -1;
+    }
+
+    register_com_android_pacprocessor_PacNative(env);
+
+    return JNI_VERSION_1_6;
+}
diff --git a/packages/services/PacProcessor/main_pacserver.cpp b/packages/services/PacProcessor/main_pacserver.cpp
deleted file mode 100644
index 19588b5..0000000
--- a/packages/services/PacProcessor/main_pacserver.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "pacserver"
-//#define LOG_NDEBUG 0
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include "ProxyService.h"
-#include "proxy_resolver_v8.h"
-#include <stdio.h>
-
-using namespace android;
-
-int main(int argc, char** argv)
-{
-    sp<ProcessState> proc(ProcessState::self());
-    sp<IServiceManager> sm = defaultServiceManager();
-
-    printf("1\n");
-    ALOGV("ServiceManager: %p", sm.get());
-    ProxyService::instantiate();
-    printf("1\n");
-
-    ProcessState::self()->startThreadPool();
-    printf("1\n");
-    IPCThreadState::self()->joinThreadPool();
-}
diff --git a/packages/services/PacProcessor/res/values/strings.xml b/packages/services/PacProcessor/res/values/strings.xml
new file mode 100644
index 0000000..301a2b6
--- /dev/null
+++ b/packages/services/PacProcessor/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">PacProcessor</string>
+
+</resources>
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java
new file mode 100644
index 0000000..c67fe9f
--- /dev/null
+++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.pacprocessor;
+
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class PacNative {
+    private static final String TAG = "PacProxy";
+
+    private String mCurrentPac;
+
+    private boolean mIsActive;
+
+    // Only make native calls from inside synchronized blocks.
+    private native boolean createV8ParserNativeLocked();
+    private native boolean destroyV8ParserNativeLocked();
+
+    private native boolean setProxyScriptNativeLocked(String script);
+
+    private native String makeProxyRequestNativeLocked(String url, String host);
+
+    static {
+        System.loadLibrary("jni_pacprocessor");
+    }
+
+    PacNative() {
+
+    }
+
+    public synchronized boolean startPacSupport() {
+        if (createV8ParserNativeLocked()) {
+            Log.e(TAG, "Unable to Create v8 Proxy Parser.");
+            return true;
+        }
+        mIsActive = true;
+        return false;
+    }
+
+    public synchronized boolean stopPacSupport() {
+        if (mIsActive) {
+            if (destroyV8ParserNativeLocked()) {
+                Log.e(TAG, "Unable to Destroy v8 Proxy Parser.");
+                return true;
+            }
+            mIsActive = false;
+        }
+        return false;
+    }
+
+    public synchronized boolean setCurrentProxyScript(String script) {
+        if (setProxyScriptNativeLocked(script)) {
+            Log.e(TAG, "Unable to parse proxy script.");
+            return true;
+        }
+        return false;
+    }
+
+    public synchronized String makeProxyRequest(String url, String host) {
+        String ret = makeProxyRequestNativeLocked(url, host);
+        if ((ret == null) || (ret.length() == 0)) {
+            Log.e(TAG, "v8 Proxy request failed.");
+            ret = null;
+        }
+        return ret;
+    }
+
+    public synchronized boolean isActive() {
+        return mIsActive;
+    }
+}
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
new file mode 100644
index 0000000..7e76025
--- /dev/null
+++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.pacprocessor;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.net.IProxyService;
+
+public class PacService extends Service {
+    private static final String TAG = "PacService";
+
+    private PacNative mPacNative;
+    private ProxyServiceStub mStub;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        if (mPacNative == null) {
+            mPacNative = new PacNative();
+            mStub = new ProxyServiceStub(mPacNative);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mPacNative != null) {
+            mPacNative.stopPacSupport();
+            mPacNative = null;
+            mStub = null;
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (mPacNative == null) {
+            mPacNative = new PacNative();
+            mStub = new ProxyServiceStub(mPacNative);
+        }
+        return mStub;
+    }
+
+    private static class ProxyServiceStub extends IProxyService.Stub {
+        private final PacNative mPacNative;
+
+        public ProxyServiceStub(PacNative pacNative) {
+            mPacNative = pacNative;
+        }
+
+        @Override
+        public String resolvePacFile(String host, String url) throws RemoteException {
+            return mPacNative.makeProxyRequest(url, host);
+        }
+
+        @Override
+        public void setPacFile(String script) throws RemoteException {
+            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+                Log.e(TAG, "Only system user is allowed to call setPacFile");
+                throw new SecurityException();
+            }
+            mPacNative.setCurrentProxyScript(script);
+        }
+
+        @Override
+        public void startPacSystem() throws RemoteException {
+            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+                Log.e(TAG, "Only system user is allowed to call startPacSystem");
+                throw new SecurityException();
+            }
+            mPacNative.startPacSupport();
+        }
+
+        @Override
+        public void stopPacSystem() throws RemoteException {
+            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+                Log.e(TAG, "Only system user is allowed to call stopPacSystem");
+                throw new SecurityException();
+            }
+            mPacNative.stopPacSupport();
+        }
+    }
+}
diff --git a/packages/services/Proxy/AndroidManifest.xml b/packages/services/Proxy/AndroidManifest.xml
index 02475c0..09b8327 100644
--- a/packages/services/Proxy/AndroidManifest.xml
+++ b/packages/services/Proxy/AndroidManifest.xml
@@ -6,7 +6,6 @@
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application
-        android:persistent="true"
         android:label="@string/app_label"
         android:process="com.android.proxyhandler">
 
diff --git a/packages/services/Proxy/com/android/net/IProxyService.aidl b/packages/services/Proxy/com/android/net/IProxyService.aidl
deleted file mode 100644
index 7e9ed79..0000000
--- a/packages/services/Proxy/com/android/net/IProxyService.aidl
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.net;
-
-/** @hide */
-interface IProxyService
-{
-    /**
-     * Keep up-to-date with
-     * frameworks/base/packages/services/PacProcessor/IProxyService.h
-     */
-    String resolvePacFile(String host, String url);
-
-    int setPacFile(String scriptContents);
-
-    int startPacSystem();
-    int stopPacSystem();
-}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
index 0aea5ee1..18ed645 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
@@ -24,24 +24,28 @@
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         if (intent != null) {
-            handleCommand(intent);
+            if (handleCommand(intent)) {
+                return START_REDELIVER_INTENT;
+            }
         }
-        return START_STICKY;
+        return START_NOT_STICKY;
     }
 
-    private void handleCommand(Intent intent) {
+    private boolean handleCommand(Intent intent) {
         Bundle bundle = intent.getExtras();
         ProxyProperties proxy = null;
         if ((bundle != null) && bundle.containsKey(Proxy.EXTRA_PROXY_INFO)) {
             proxy = bundle.getParcelable(Proxy.EXTRA_PROXY_INFO);
             if ((proxy != null) && !TextUtils.isEmpty(proxy.getPacFileUrl())) {
                 startProxy(proxy);
+                return true;
             } else {
                 stopSelf();
             }
         } else {
             stopSelf();
         }
+        return false;
     }
 
 
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java
index f5c2ca5..4638def 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java
@@ -4,7 +4,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Proxy;
+import android.net.ProxyProperties;
 import android.os.Bundle;
+import android.text.TextUtils;
 
 public class ProxyServiceReceiver extends BroadcastReceiver {
 
@@ -12,11 +14,16 @@
     public void onReceive(Context context, Intent intent) {
         Intent service = new Intent(context, ProxyService.class);
         Bundle bundle = intent.getExtras();
+        ProxyProperties proxy = null;
         if (bundle != null) {
-            service.putExtra(Proxy.EXTRA_PROXY_INFO,
-                    bundle.getParcelable(Proxy.EXTRA_PROXY_INFO));
+            proxy = bundle.getParcelable(Proxy.EXTRA_PROXY_INFO);
+            service.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
         }
-        context.startService(service);
+        if ((proxy != null) && (!TextUtils.isEmpty(proxy.getPacFileUrl()))) {
+            context.startService(service);
+        } else {
+            context.stopService(service);
+        }
     }
 
 }
diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java
index fb76e20b..bcecff2 100644
--- a/policy/src/com/android/internal/policy/impl/BarController.java
+++ b/policy/src/com/android/internal/policy/impl/BarController.java
@@ -40,18 +40,21 @@
 
     private final String mTag;
     private final int mTransientFlag;
+    private final int mUnhideFlag;
     private final int mStatusBarManagerId;
     private final Handler mHandler;
     private final Object mServiceAquireLock = new Object();
     private IStatusBarService mStatusBarService;
 
     private WindowState mWin;
+    private int mState;
     private int mTransientBarState;
     private boolean mPendingShow;
 
-    public BarController(String tag, int transientFlag, int statusBarManagerId) {
+    public BarController(String tag, int transientFlag, int unhideFlag, int statusBarManagerId) {
         mTag = "BarController." + tag;
         mTransientFlag = transientFlag;
+        mUnhideFlag = unhideFlag;
         mStatusBarManagerId = statusBarManagerId;
         mHandler = new Handler();
     }
@@ -60,6 +63,10 @@
         mWin = win;
     }
 
+    public boolean isHidden() {
+        return mState == StatusBarManager.WINDOW_STATE_HIDDEN;
+    }
+
     public void showTransient() {
         if (mWin != null) {
             setTransientBarState(TRANSIENT_BAR_SHOWING);
@@ -70,49 +77,75 @@
         return mTransientBarState == TRANSIENT_BAR_SHOWING;
     }
 
-    public void adjustSystemUiVisibilityLw(int visibility) {
+    public void adjustSystemUiVisibilityLw(int oldVis, int vis) {
         if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
-                (visibility & mTransientFlag) == 0) {
+                (vis & mTransientFlag) == 0) {
+            // sysui requests hide
             setTransientBarState(TRANSIENT_BAR_HIDING);
             setBarShowingLw(false);
+        } else if (mWin != null && (oldVis & mUnhideFlag) != 0 && (vis & mUnhideFlag) == 0) {
+            // sysui ready to unhide
+            setBarShowingLw(true);
         }
     }
 
     public boolean setBarShowingLw(final boolean show) {
         if (mWin == null) return false;
-
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    IStatusBarService statusbar = getStatusBarService();
-                    if (statusbar != null) {
-                        statusbar.setWindowState(mStatusBarManagerId, show
-                                ? StatusBarManager.WINDOW_STATE_SHOWING
-                                : StatusBarManager.WINDOW_STATE_HIDING);
-                    }
-                } catch (RemoteException e) {
-                    // re-acquire status bar service next time it is needed.
-                    mStatusBarService = null;
-                }
-            }
-        });
         if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
             mPendingShow = true;
             return false;
         }
-        return show ? mWin.showLw(true) : mWin.hideLw(true);
+        final boolean oldVis = mWin.isVisibleLw();
+        final boolean oldAnim = mWin.isAnimatingLw();
+        final boolean rt = show ? mWin.showLw(true) : mWin.hideLw(true);
+        final int state = computeState(oldVis, oldAnim, mWin.isVisibleLw(), mWin.isAnimatingLw());
+        if (state > -1) {
+            updateState(state);
+        }
+        return rt;
+    }
+
+    private int computeState(boolean oldVis, boolean oldAnim, boolean newVis, boolean newAnim) {
+        return (!newVis && !newAnim) ? StatusBarManager.WINDOW_STATE_HIDDEN
+                : (!oldVis && newVis && newAnim) ? StatusBarManager.WINDOW_STATE_SHOWING
+                : (oldVis && newVis && !oldAnim && newAnim) ? StatusBarManager.WINDOW_STATE_HIDING
+                : -1;
+    }
+
+    private void updateState(final int state) {
+        if (state != mState) {
+            mState = state;
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        IStatusBarService statusbar = getStatusBarService();
+                        if (statusbar != null) {
+                            statusbar.setWindowState(mStatusBarManagerId, state);
+                        }
+                    } catch (RemoteException e) {
+                        // re-acquire status bar service next time it is needed.
+                        mStatusBarService = null;
+                    }
+                }
+            });
+        }
     }
 
     public boolean checkHiddenLw() {
-        if (mWin != null && mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
-            // Finished animating out, clean up and reset style
-            setTransientBarState(TRANSIENT_BAR_NONE);
-            if (mPendingShow) {
-                setBarShowingLw(true);
-                mPendingShow = false;
+        if (mWin != null) {
+            if (!mWin.isVisibleLw() && !mWin.isAnimatingLw()) {
+                updateState(StatusBarManager.WINDOW_STATE_HIDDEN);
             }
-            return true;
+            if (mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
+                // Finished animating out, clean up and reset style
+                setTransientBarState(TRANSIENT_BAR_NONE);
+                if (mPendingShow) {
+                    setBarShowingLw(true);
+                    mPendingShow = false;
+                }
+                return true;
+            }
         }
         return false;
     }
@@ -134,12 +167,11 @@
 
     public int updateVisibilityLw(boolean allowed, int oldVis, int vis) {
         if (mWin == null) return vis;
-
         if (mTransientBarState == TRANSIENT_BAR_SHOWING) { // transient bar requested
             if (allowed) {
                 vis |= mTransientFlag;
                 if ((oldVis & mTransientFlag) == 0) {
-                    setBarShowingLw(true);
+                    vis |= mUnhideFlag;  // tell sysui we're ready to unhide
                 }
             } else {
                 setTransientBarState(TRANSIENT_BAR_NONE);  // request denied
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 11e33dc..f3e7f0a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -554,9 +554,15 @@
     MyOrientationListener mOrientationListener;
 
     private final BarController mStatusBarController = new BarController("StatusBar",
-            View.STATUS_BAR_TRANSIENT, StatusBarManager.WINDOW_STATUS_BAR);
+            View.STATUS_BAR_TRANSIENT,
+            View.STATUS_BAR_UNHIDE,
+            StatusBarManager.WINDOW_STATUS_BAR);
+
     private final BarController mNavigationBarController = new BarController("NavigationBar",
-            View.NAVIGATION_BAR_TRANSIENT, StatusBarManager.WINDOW_NAVIGATION_BAR);
+            View.NAVIGATION_BAR_TRANSIENT,
+            View.NAVIGATION_BAR_UNHIDE,
+            StatusBarManager.WINDOW_NAVIGATION_BAR);
+
     private TransientNavigationConfirmation mTransientNavigationConfirmation;
 
     private SystemGesturesPointerEventListener mSystemGestures;
@@ -2551,8 +2557,8 @@
 
     @Override
     public int adjustSystemUiVisibilityLw(int visibility) {
-        mStatusBarController.adjustSystemUiVisibilityLw(visibility);
-        mNavigationBarController.adjustSystemUiVisibilityLw(visibility);
+        mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
+        mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
 
         // Reset any bits in mForceClearingStatusBarVisibility that
         // are now clear.
@@ -5084,6 +5090,10 @@
         }
         vis = mNavigationBarController.updateVisibilityLw(isTransientNav, oldVis, vis);
 
+        // don't send low profile updates if the system bars are hidden
+        if (mStatusBarController.isHidden() && mNavigationBarController.isHidden()) {
+            vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
+        }
         return vis;
     }
 
diff --git a/services/java/Android.mk b/services/java/Android.mk
index 95b28d9..8c3d0f0 100644
--- a/services/java/Android.mk
+++ b/services/java/Android.mk
@@ -11,7 +11,7 @@
 
 LOCAL_MODULE:= services
 
-LOCAL_JAVA_LIBRARIES := android.policy telephony-common
+LOCAL_JAVA_LIBRARIES := android.policy conscrypt telephony-common
 
 include $(BUILD_JAVA_LIBRARY)
 
diff --git a/services/java/com/android/server/CommonTimeManagementService.java b/services/java/com/android/server/CommonTimeManagementService.java
index aa2c8b8..710fb9d 100644
--- a/services/java/com/android/server/CommonTimeManagementService.java
+++ b/services/java/com/android/server/CommonTimeManagementService.java
@@ -40,6 +40,8 @@
 import android.os.SystemProperties;
 import android.util.Log;
 
+import com.android.server.net.BaseNetworkObserver;
+
 /**
  * @hide
  * <p>CommonTimeManagementService manages the configuration of the native Common Time service,
@@ -104,9 +106,7 @@
     /*
      * Callback handler implementations.
      */
-    private INetworkManagementEventObserver mIfaceObserver =
-        new INetworkManagementEventObserver.Stub() {
-
+    private INetworkManagementEventObserver mIfaceObserver = new BaseNetworkObserver() {
         public void interfaceStatusChanged(String iface, boolean up) {
             reevaluateServiceState();
         }
@@ -119,9 +119,6 @@
         public void interfaceRemoved(String iface) {
             reevaluateServiceState();
         }
-        public void limitReached(String limitName, String iface) { }
-
-        public void interfaceClassDataActivityChanged(String label, boolean active) {}
     };
 
     private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index a0e6dd1..ec6b063 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -31,6 +31,7 @@
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 
+import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -56,6 +57,7 @@
 import android.net.INetworkStatsService;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.LinkInfo;
 import android.net.LinkProperties.CompareResult;
 import android.net.MobileDataStateTracker;
 import android.net.NetworkConfig;
@@ -68,6 +70,7 @@
 import android.net.Proxy;
 import android.net.ProxyProperties;
 import android.net.RouteInfo;
+import android.net.SamplingDataTracker;
 import android.net.Uri;
 import android.net.wifi.WifiStateTracker;
 import android.net.wimax.WimaxManagerConstants;
@@ -144,8 +147,10 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.GregorianCalendar;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -174,6 +179,23 @@
     private static final String FAIL_FAST_TIME_MS =
             "persist.radio.fail_fast_time_ms";
 
+    private static final String ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED =
+            "android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED";
+
+    private static final int SAMPLE_INTERVAL_ELAPSED_REQURST_CODE = 0;
+
+    private PendingIntent mSampleIntervalElapsedIntent;
+
+    // Set network sampling interval at 12 minutes, this way, even if the timers get
+    // aggregated, it will fire at around 15 minutes, which should allow us to
+    // aggregate this timer with other timers (specially the socket keep alive timers)
+    private static final int DEFAULT_SAMPLING_INTERVAL_IN_SECONDS = (VDBG ? 30 : 12 * 60);
+
+    // start network sampling a minute after booting ...
+    private static final int DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS = (VDBG ? 30 : 60);
+
+    AlarmManager mAlarmManager;
+
     // used in recursive route setting to add gateways for the host for which
     // a host route was requested.
     private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
@@ -326,6 +348,11 @@
      */
     private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14;
 
+    /**
+     * user internally to indicate that data sampling interval is up
+     */
+    private static final int EVENT_SAMPLE_INTERVAL_ELAPSED = 15;
+
     /** Handler used for internal events. */
     private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -392,6 +419,7 @@
     List mProtectedNetworks;
 
     private DataConnectionStats mDataConnectionStats;
+
     private AtomicInteger mEnableFailFastMobileDataTag = new AtomicInteger(0);
 
     TelephonyManager mTelephonyManager;
@@ -634,6 +662,29 @@
         mDataConnectionStats = new DataConnectionStats(mContext);
         mDataConnectionStats.startMonitoring();
 
+        // start network sampling ..
+        Intent intent = new Intent(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED, null);
+        mSampleIntervalElapsedIntent = PendingIntent.getBroadcast(mContext,
+                SAMPLE_INTERVAL_ELAPSED_REQURST_CODE, intent, 0);
+
+        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+        setAlarm(DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS * 1000, mSampleIntervalElapsedIntent);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED);
+        mContext.registerReceiver(
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        String action = intent.getAction();
+                        if (action.equals(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED)) {
+                            mHandler.sendMessage(mHandler.obtainMessage
+                                    (EVENT_SAMPLE_INTERVAL_ELAPSED));
+                        }
+                    }
+                },
+                new IntentFilter(filter));
+
         mPacManager = new PacManager(mContext);
     }
 
@@ -1911,6 +1962,7 @@
 //            if (mActiveDefaultNetwork != -1) {
 //                currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
 //            }
+
             for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
                 if (checkType == prevNetType) continue;
                 if (mNetConfigs[checkType] == null) continue;
@@ -1925,6 +1977,7 @@
 // optimization should work and we need to investigate why it doesn't work.
 // This could be related to how DEACTIVATE_DATA_CALL is reporting its
 // complete before it is really complete.
+
 //                if (!mNetTrackers[checkType].isAvailable()) continue;
 
 //                if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
@@ -2520,12 +2573,12 @@
     }
 
 
-   /**
+    /**
      * Reads the network specific TCP buffer sizes from SystemProperties
      * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
      * wide use
      */
-   private void updateNetworkSettings(NetworkStateTracker nt) {
+    private void updateNetworkSettings(NetworkStateTracker nt) {
         String key = nt.getTcpBufferSizesPropName();
         String bufferSizes = key == null ? null : SystemProperties.get(key);
 
@@ -2547,7 +2600,7 @@
         }
     }
 
-   /**
+    /**
      * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
      * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
      *
@@ -2956,6 +3009,9 @@
                                 + " != tag:" + tag);
                     }
                 }
+                case EVENT_SAMPLE_INTERVAL_ELAPSED:
+                    handleNetworkSamplingTimeout();
+                    break;
             }
         }
     }
@@ -3982,8 +4038,8 @@
                         // Get the type of addresses supported by this link
                         LinkProperties lp = mCs.getLinkProperties(
                                 ConnectivityManager.TYPE_MOBILE_HIPRI);
-                        boolean linkHasIpv4 = hasIPv4Address(lp);
-                        boolean linkHasIpv6 = hasIPv6Address(lp);
+                        boolean linkHasIpv4 = lp.hasIPv4Address();
+                        boolean linkHasIpv6 = lp.hasIPv6Address();
                         log("isMobileOk: linkHasIpv4=" + linkHasIpv4
                                 + " linkHasIpv6=" + linkHasIpv6);
 
@@ -4129,20 +4185,6 @@
             }
         }
 
-        public boolean hasIPv4Address(LinkProperties lp) {
-            return lp.hasIPv4Address();
-        }
-
-        // Not implemented in LinkProperties, do it here.
-        public boolean hasIPv6Address(LinkProperties lp) {
-            for (LinkAddress address : lp.getLinkAddresses()) {
-              if (address.getAddress() instanceof Inet6Address) {
-                return true;
-              }
-            }
-            return false;
-        }
-
         private void log(String s) {
             Slog.d(ConnectivityService.TAG, "[" + CHECKMP_TAG + "] " + s);
         }
@@ -4371,4 +4413,92 @@
             }
         }
     };
+
+    @Override
+    public LinkInfo getLinkInfo(int networkType) {
+        enforceAccessPermission();
+        if (isNetworkTypeValid(networkType)) {
+            return mNetTrackers[networkType].getLinkInfo();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public LinkInfo getActiveLinkInfo() {
+        enforceAccessPermission();
+        if (isNetworkTypeValid(mActiveDefaultNetwork)) {
+            return mNetTrackers[mActiveDefaultNetwork].getLinkInfo();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public LinkInfo[] getAllLinkInfo() {
+        enforceAccessPermission();
+        final ArrayList<LinkInfo> result = Lists.newArrayList();
+        for (NetworkStateTracker tracker : mNetTrackers) {
+            if (tracker != null) {
+                LinkInfo li = tracker.getLinkInfo();
+                if (li != null) {
+                    result.add(li);
+                }
+            }
+        }
+
+        return result.toArray(new LinkInfo[result.size()]);
+    }
+
+    /* Infrastructure for network sampling */
+
+    private void handleNetworkSamplingTimeout() {
+
+        log("Sampling interval elapsed, updating statistics ..");
+
+        // initialize list of interfaces ..
+        Map<String, SamplingDataTracker.SamplingSnapshot> mapIfaceToSample =
+                new HashMap<String, SamplingDataTracker.SamplingSnapshot>();
+        for (NetworkStateTracker tracker : mNetTrackers) {
+            if (tracker != null) {
+                String ifaceName = tracker.getNetworkInterfaceName();
+                if (ifaceName != null) {
+                    mapIfaceToSample.put(ifaceName, null);
+                }
+            }
+        }
+
+        // Read samples for all interfaces
+        SamplingDataTracker.getSamplingSnapshots(mapIfaceToSample);
+
+        // process samples for all networks
+        for (NetworkStateTracker tracker : mNetTrackers) {
+            if (tracker != null) {
+                String ifaceName = tracker.getNetworkInterfaceName();
+                SamplingDataTracker.SamplingSnapshot ss = mapIfaceToSample.get(ifaceName);
+                if (ss != null) {
+                    // end the previous sampling cycle
+                    tracker.stopSampling(ss);
+                    // start a new sampling cycle ..
+                    tracker.startSampling(ss);
+                }
+            }
+        }
+
+        log("Done.");
+
+        int samplingIntervalInSeconds = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
+                DEFAULT_SAMPLING_INTERVAL_IN_SECONDS);
+
+        if (DBG) log("Setting timer for " + String.valueOf(samplingIntervalInSeconds) + "seconds");
+
+        setAlarm(samplingIntervalInSeconds * 1000, mSampleIntervalElapsedIntent);
+    }
+
+    void setAlarm(int timeoutInMilliseconds, PendingIntent intent) {
+        long wakeupTime = SystemClock.elapsedRealtime() + timeoutInMilliseconds;
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime, intent);
+    }
 }
+
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 43f95c3..7e83396 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -16,11 +16,14 @@
 
 package com.android.server;
 
+import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+
 import com.android.internal.os.storage.ExternalStorageFormatter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.org.conscrypt.TrustedCertificateStore;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -49,6 +52,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -66,7 +70,12 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.security.Credentials;
+import android.security.IKeyChainService;
+import android.security.KeyChain;
+import android.security.KeyChain.KeyChainConnection;
 import android.util.AtomicFile;
+import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.Slog;
@@ -75,6 +84,7 @@
 import android.view.IWindowManager;
 import android.view.WindowManagerPolicy;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -82,8 +92,14 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -1870,6 +1886,76 @@
         return !"".equals(state);
     }
 
+    public boolean installCaCert(byte[] certBuffer) throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
+        KeyChainConnection keyChainConnection = null;
+        byte[] pemCert;
+        try {
+            X509Certificate cert = parseCert(certBuffer);
+            pemCert =  Credentials.convertToPem(cert);
+        } catch (CertificateException ce) {
+            Log.e(TAG, "Problem converting cert", ce);
+            return false;
+        } catch (IOException ioe) {
+            Log.e(TAG, "Problem reading cert", ioe);
+            return false;
+        }
+        try {
+            keyChainConnection = KeyChain.bind(mContext);
+            try {
+                keyChainConnection.getService().installCaCertificate(pemCert);
+                return true;
+            } finally {
+                if (keyChainConnection != null) {
+                    keyChainConnection.close();
+                    keyChainConnection = null;
+                }
+            }
+        } catch (InterruptedException e1) {
+            Log.w(TAG, "installCaCertsToKeyChain(): ", e1);
+            Thread.currentThread().interrupt();
+        }
+        return false;
+    }
+
+    private static X509Certificate parseCert(byte[] certBuffer)
+            throws CertificateException, IOException {
+        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(
+                certBuffer));
+    }
+
+    public void uninstallCaCert(final byte[] certBuffer) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
+        TrustedCertificateStore certStore = new TrustedCertificateStore();
+        String alias = null;
+        try {
+            X509Certificate cert = parseCert(certBuffer);
+            alias = certStore.getCertificateAlias(cert);
+        } catch (CertificateException ce) {
+            Log.e(TAG, "Problem creating X509Certificate", ce);
+            return;
+        } catch (IOException ioe) {
+            Log.e(TAG, "Problem reading certificate", ioe);
+            return;
+        }
+        try {
+            KeyChainConnection keyChainConnection = KeyChain.bind(mContext);
+            IKeyChainService service = keyChainConnection.getService();
+            try {
+                service.deleteCaCertificate(alias);
+            } catch (RemoteException e) {
+                Log.e(TAG, "from CaCertUninstaller: ", e);
+            } finally {
+                keyChainConnection.close();
+                keyChainConnection = null;
+            }
+        } catch (InterruptedException ie) {
+            Log.w(TAG, "CaCertUninstaller: ", ie);
+            Thread.currentThread().interrupt();
+        }
+    }
+
     void wipeDataLocked(int flags) {
         // If the SD card is encrypted and non-removable, we have to force a wipe.
         boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 9761441..95c768f 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1235,8 +1235,11 @@
                     if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
                         LocationRequest locationRequest = record.mRequest;
                         if (locationRequest.getInterval() <= thresholdInterval) {
-                            if (record.mReceiver.mWorkSource != null) {
+                            if (record.mReceiver.mWorkSource != null
+                                    && record.mReceiver.mWorkSource.size() > 0
+                                    && record.mReceiver.mWorkSource.getName(0) != null) {
                                 // Assign blame to another work source.
+                                // Can only assign blame if the WorkSource contains names.
                                 worksource.add(record.mReceiver.mWorkSource);
                             } else {
                                 // Assign blame to caller.
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 988b1f2..16cfa666 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -133,6 +133,7 @@
         public static final int InterfaceChange           = 600;
         public static final int BandwidthControl          = 601;
         public static final int InterfaceClassActivity    = 613;
+        public static final int InterfaceAddressChange    = 614;
     }
 
     /**
@@ -393,6 +394,36 @@
         setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());
     }
 
+    /**
+     * Notify our observers of a new or updated interface address.
+     */
+    private void notifyAddressUpdated(String address, String iface, int flags, int scope) {
+        final int length = mObservers.beginBroadcast();
+        for (int i = 0; i < length; i++) {
+            try {
+                mObservers.getBroadcastItem(i).addressUpdated(address, iface, flags, scope);
+            } catch (RemoteException e) {
+            } catch (RuntimeException e) {
+            }
+        }
+        mObservers.finishBroadcast();
+    }
+
+    /**
+     * Notify our observers of a deleted interface address.
+     */
+    private void notifyAddressRemoved(String address, String iface, int flags, int scope) {
+        final int length = mObservers.beginBroadcast();
+        for (int i = 0; i < length; i++) {
+            try {
+                mObservers.getBroadcastItem(i).addressRemoved(address, iface, flags, scope);
+            } catch (RemoteException e) {
+            } catch (RuntimeException e) {
+            }
+        }
+        mObservers.finishBroadcast();
+    }
+
     //
     // Netd Callback handling
     //
@@ -475,6 +506,32 @@
                     notifyInterfaceClassActivity(cooked[3], isActive);
                     return true;
                     // break;
+            case NetdResponseCode.InterfaceAddressChange:
+                    /*
+                     * A network address change occurred
+                     * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
+                     *         "NNN Address removed <addr> <iface> <flags> <scope>"
+                     */
+                    String msg = String.format("Invalid event from daemon (%s)", raw);
+                    if (cooked.length < 6 || !cooked[1].equals("Address")) {
+                        throw new IllegalStateException(msg);
+                    }
+
+                    int flags, scope;
+                    try {
+                        flags = Integer.parseInt(cooked[5]);
+                        scope = Integer.parseInt(cooked[6]);
+                    } catch(NumberFormatException e) {
+                        throw new IllegalStateException(msg);
+                    }
+
+                    if (cooked[2].equals("updated")) {
+                        notifyAddressUpdated(cooked[3], cooked[4], flags, scope);
+                    } else {
+                        notifyAddressRemoved(cooked[3], cooked[4], flags, scope);
+                    }
+                    return true;
+                    // break;
             default: break;
             }
             return false;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3f58fa4..8f4b6c2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -8154,18 +8154,20 @@
     }
 
     @Override
-    public void convertFromTranslucent(IBinder token) {
+    public boolean convertFromTranslucent(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
                 if (r == null) {
-                    return;
+                    return false;
                 }
                 if (r.changeWindowTranslucency(true)) {
                     mWindowManager.setAppFullscreen(token, true);
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+                    return true;
                 }
+                return false;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -8173,19 +8175,21 @@
     }
 
     @Override
-    public void convertToTranslucent(IBinder token) {
+    public boolean convertToTranslucent(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
                 if (r == null) {
-                    return;
+                    return false;
                 }
                 if (r.changeWindowTranslucency(false)) {
                     r.task.stack.convertToTranslucent(r);
                     mWindowManager.setAppFullscreen(token, false);
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+                    return true;
                 }
+                return false;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index defe9f0..0b68ff5 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -1,14 +1,31 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.server.connectivity;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.net.ConnectivityManager;
+import android.content.ServiceConnection;
 import android.net.ProxyProperties;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -17,42 +34,26 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.net.IProxyService;
+import com.android.server.IoThread;
 
+import libcore.io.Streams;
 
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.params.ConnRouteParams;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.conn.routing.HttpRoutePlanner;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.HttpContext;
-
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetAddress;
-import java.net.ProxySelector;
 import java.net.URL;
 import java.net.URLConnection;
 
 /**
  * @hide
  */
-public class PacManager implements Runnable {
-    public static final int NO_ERROR = 0;
-    public static final int PERMISSION_DENIED = 1;
-    public static final String PROXY_SERVICE = "com.android.net.IProxyService";
+public class PacManager {
+    public static final String PROXY_PACKAGE = "com.android.pacprocessor";
+    public static final String PROXY_SERVICE = "com.android.pacprocessor.PacService";
+    public static final String PROXY_SERVICE_NAME = "com.android.net.IProxyService";
 
 
-    private static final String TAG = "PACManager";
+    private static final String TAG = "PacManager";
 
     private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH";
 
@@ -64,31 +65,57 @@
     /** Keep these values up-to-date with ProxyService.java */
     public static final String KEY_PROXY = "keyProxy";
     private String mCurrentPac;
-    private volatile String mPacUrl;
+    @GuardedBy("mProxyLock")
+    private String mPacUrl;
 
     private AlarmManager mAlarmManager;
+    @GuardedBy("mProxyLock")
     private IProxyService mProxyService;
     private PendingIntent mPacRefreshIntent;
+    private ServiceConnection mConnection;
     private Context mContext;
 
     private int mCurrentDelay;
 
+    /**
+     * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
+     */
+    private final Object mProxyLock = new Object();
+
+    private Runnable mPacDownloader = new Runnable() {
+        @Override
+        public void run() {
+            String file;
+            synchronized (mProxyLock) {
+                if (mPacUrl == null) return;
+                try {
+                    file = get(mPacUrl);
+                } catch (IOException ioe) {
+                    file = null;
+                    Log.w(TAG, "Failed to load PAC file: " + ioe);
+                }
+            }
+            if (file != null) {
+                synchronized (mProxyLock) {
+                    if (!file.equals(mCurrentPac)) {
+                        setCurrentProxyScript(file);
+                    }
+                }
+                longSchedule();
+            } else {
+                reschedule();
+            }
+        }
+    };
+
     class PacRefreshIntentReceiver extends BroadcastReceiver {
         public void onReceive(Context context, Intent intent) {
-            new Thread(PacManager.this).start();
+            IoThread.getHandler().post(mPacDownloader);
         }
     }
 
     public PacManager(Context context) {
         mContext = context;
-        mProxyService = IProxyService.Stub.asInterface(
-                ServiceManager.getService(PROXY_SERVICE));
-        if (mProxyService == null) {
-            // Added because of b10267814 where mako is restarting.
-            Log.e(TAG, "PacManager: no proxy service");
-        } else {
-            Log.d(TAG, "PacManager: mProxyService available");
-        }
 
         mPacRefreshIntent = PendingIntent.getBroadcast(
                 context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -103,26 +130,28 @@
         return mAlarmManager;
     }
 
-    public void setCurrentProxyScriptUrl(ProxyProperties proxy) {
-        if (mProxyService == null) {
-            Log.e(TAG, "setCurrentProxyScriptUrl: no proxy service");
-            return;
-        }
+    public synchronized void setCurrentProxyScriptUrl(ProxyProperties proxy) {
         if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
-            try {
-                mProxyService.startPacSystem();
+            synchronized (mProxyLock) {
                 mPacUrl = proxy.getPacFileUrl();
-                mCurrentDelay = DELAY_1;
-                getAlarmManager().cancel(mPacRefreshIntent);
-                new Thread(this).start();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
             }
+            mCurrentDelay = DELAY_1;
+            getAlarmManager().cancel(mPacRefreshIntent);
+            bind();
         } else {
-            try {
-                mProxyService.stopPacSystem();
-            } catch (RemoteException e) {
-                e.printStackTrace();
+            getAlarmManager().cancel(mPacRefreshIntent);
+            synchronized (mProxyLock) {
+                mPacUrl = null;
+                mCurrentPac = null;
+                if (mProxyService != null) {
+                    try {
+                        mProxyService.stopPacSystem();
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to stop PAC service", e);
+                    } finally {
+                        unbind();
+                    }
+                }
             }
         }
     }
@@ -132,51 +161,10 @@
      *
      * @throws IOException
      */
-    public static String get(String urlString) throws IOException {
+    private static String get(String urlString) throws IOException {
         URL url = new URL(urlString);
         URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
-        BufferedReader in = new BufferedReader(new InputStreamReader(
-                urlConnection.getInputStream()));
-        String inputLine;
-        String resp = "";
-        while ((inputLine = in.readLine()) != null) {
-            resp = resp + inputLine + "\n";
-        }
-        in.close();
-        return resp;
-    }
-
-    private static String toString(InputStream content) throws IOException {
-        StringBuffer buffer = new StringBuffer();
-        String line;
-        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(content));
-
-        while ((line = bufferedReader.readLine()) != null) {
-            if (buffer.length() != 0) {
-                buffer.append('\n');
-            }
-            buffer.append(line);
-        }
-
-        return buffer.toString();
-    }
-
-    @Override
-    public void run() {
-        String file;
-        try {
-            file = get(mPacUrl);
-        } catch (IOException ioe) {
-            file = null;
-        }
-        if (file != null) {
-            if (!file.equals(mCurrentPac)) {
-                setCurrentProxyScript(file);
-            }
-            longSchedule();
-        } else {
-            reschedule();
-        }
+        return new String(Streams.readFully(urlConnection.getInputStream()));
     }
 
     private int getNextDelay(int currentDelay) {
@@ -227,14 +215,60 @@
             return false;
         }
         try {
-            if (mProxyService.setPacFile(script) != NO_ERROR) {
-                Log.e(TAG, "Unable to parse proxy script.");
-                return false;
-            }
+            mProxyService.setPacFile(script);
             mCurrentPac = script;
         } catch (RemoteException e) {
             Log.e(TAG, "Unable to set PAC file", e);
         }
         return true;
     }
+
+    private void bind() {
+        if (mContext == null) {
+            Log.e(TAG, "No context for binding");
+            return;
+        }
+        Intent intent = new Intent();
+        intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE);
+        mConnection = new ServiceConnection() {
+            @Override
+            public void onServiceDisconnected(ComponentName component) {
+                synchronized (mProxyLock) {
+                    mProxyService = null;
+                }
+            }
+
+            @Override
+            public void onServiceConnected(ComponentName component, IBinder binder) {
+                synchronized (mProxyLock) {
+                    try {
+                        Log.d(TAG, "Adding service " + PROXY_SERVICE_NAME + " "
+                                + binder.getInterfaceDescriptor());
+                    } catch (RemoteException e1) {
+                        Log.e(TAG, "Remote Exception", e1);
+                    }
+                    ServiceManager.addService(PROXY_SERVICE_NAME, binder);
+                    mProxyService = IProxyService.Stub.asInterface(binder);
+                    if (mProxyService == null) {
+                        Log.e(TAG, "No proxy service");
+                    } else {
+                        try {
+                            mProxyService.startPacSystem();
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
+                        }
+                        IoThread.getHandler().post(mPacDownloader);
+                    }
+                }
+            }
+        };
+        Log.e(TAG, "Attempting to bind");
+        mContext.bindService(intent, mConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
+    }
+
+    private void unbind() {
+        mContext.unbindService(mConnection);
+        mConnection = null;
+    }
 }
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 22a7841..fb4c1cf 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -315,6 +315,10 @@
         }
     }
 
+    public void addressUpdated(String address, String iface, int flags, int scope) {}
+
+    public void addressRemoved(String address, String iface, int flags, int scope) {}
+
     public void limitReached(String limitName, String iface) {}
 
     public void interfaceClassDataActivityChanged(String label, boolean active) {}
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index f89917c3..846a74d 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -83,11 +83,6 @@
     private static final int CONNECT_MAX_RETRIES = 3;
     private static final int CONNECT_RETRY_DELAY_MILLIS = 500;
 
-    // A unique token to identify the remote submix that is managed by Wifi display.
-    // It must match what the media server uses when it starts recording the submix
-    // for transmission.  We use 0 although the actual value is currently ignored.
-    private static final int REMOTE_SUBMIX_ADDRESS = 0;
-
     private final Context mContext;
     private final Handler mHandler;
     private final Listener mListener;
@@ -95,8 +90,6 @@
     private final WifiP2pManager mWifiP2pManager;
     private final Channel mWifiP2pChannel;
 
-    private final AudioManager mAudioManager;
-
     private boolean mWifiP2pEnabled;
     private boolean mWfdEnabled;
     private boolean mWfdEnabling;
@@ -146,9 +139,6 @@
     // True if RTSP has connected.
     private boolean mRemoteDisplayConnected;
 
-    // True if the remote submix is enabled.
-    private boolean mRemoteSubmixOn;
-
     // The information we have most recently told WifiDisplayAdapter about.
     private WifiDisplay mAdvertisedDisplay;
     private Surface mAdvertisedDisplaySurface;
@@ -164,8 +154,6 @@
         mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE);
         mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null);
 
-        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
         intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
@@ -211,7 +199,6 @@
         pw.println("mRemoteDisplay=" + mRemoteDisplay);
         pw.println("mRemoteDisplayInterface=" + mRemoteDisplayInterface);
         pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected);
-        pw.println("mRemoteSubmixOn=" + mRemoteSubmixOn);
         pw.println("mAdvertisedDisplay=" + mAdvertisedDisplay);
         pw.println("mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface);
         pw.println("mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth);
@@ -482,7 +469,6 @@
             mHandler.removeCallbacks(mRtspTimeout);
 
             mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED);
-            setRemoteSubmixOn(false);
             unadvertiseDisplay();
 
             // continue to next step
@@ -626,7 +612,6 @@
                 return; // done
             }
 
-            setRemoteSubmixOn(true);
             mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE);
 
             final WifiP2pDevice oldDevice = mConnectedDevice;
@@ -677,13 +662,6 @@
         }
     }
 
-    private void setRemoteSubmixOn(boolean on) {
-        if (mRemoteSubmixOn != on) {
-            mRemoteSubmixOn = on;
-            mAudioManager.setRemoteSubmixOn(on, REMOTE_SUBMIX_ADDRESS);
-        }
-    }
-
     private void handleStateChanged(boolean enabled) {
         mWifiP2pEnabled = enabled;
         updateWfdEnableState();
diff --git a/services/java/com/android/server/net/BaseNetworkObserver.java b/services/java/com/android/server/net/BaseNetworkObserver.java
deleted file mode 100644
index 8b2aa5d..0000000
--- a/services/java/com/android/server/net/BaseNetworkObserver.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import android.net.INetworkManagementEventObserver;
-
-/**
- * Base {@link INetworkManagementEventObserver} that provides no-op
- * implementations which can be overridden.
- *
- * @hide
- */
-public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub {
-    @Override
-    public void interfaceStatusChanged(String iface, boolean up) {
-        // default no-op
-    }
-
-    @Override
-    public void interfaceRemoved(String iface) {
-        // default no-op
-    }
-
-    @Override
-    public void interfaceLinkStateChanged(String iface, boolean up) {
-        // default no-op
-    }
-
-    @Override
-    public void interfaceAdded(String iface) {
-        // default no-op
-    }
-
-    @Override
-    public void interfaceClassDataActivityChanged(String label, boolean active) {
-        // default no-op
-    }
-
-    @Override
-    public void limitReached(String limitName, String iface) {
-        // default no-op
-    }
-}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 491dddc..5c684601 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -30,8 +30,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.print.IPrinterDiscoverySessionController;
-import android.print.IPrinterDiscoverySessionObserver;
 import android.print.PrintJobInfo;
 import android.print.PrintManager;
 import android.print.PrinterId;
@@ -79,6 +77,10 @@
 
     private boolean mDestroyed;
 
+    private boolean mAllPrintJobsHandled;
+
+    private boolean mHasPrinterDiscoverySession;
+
     public RemotePrintService(Context context, ComponentName componentName, int userId,
             RemotePrintSpooler spooler) {
         mContext = context;
@@ -97,6 +99,8 @@
     private void handleDestroy() {
         throwIfDestroyed();
         ensureUnbound();
+        mAllPrintJobsHandled = false;
+        mHasPrinterDiscoverySession = false;
         mDestroyed = true;
     }
 
@@ -110,18 +114,27 @@
     }
 
     private void handleBinderDied() {
+        mAllPrintJobsHandled = false;
+        mHasPrinterDiscoverySession = false;
         mPendingCommands.clear();
         ensureUnbound();
     }
 
     private void handleOnAllPrintJobsHandled() {
         throwIfDestroyed();
+
+        mAllPrintJobsHandled = true;
+
         if (isBound()) {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserId + "] handleOnAllPrintJobsHandled()");
             }
-            // If bound and all the work is completed, then unbind.
-            ensureUnbound();
+
+            // If the service has a printer discovery session
+            // created we should not disconnect from it just yet.
+            if (!mHasPrinterDiscoverySession) {
+                ensureUnbound();
+            }
         }
     }
 
@@ -153,6 +166,9 @@
 
     private void handleOnPrintJobQueued(final PrintJobInfo printJob) {
         throwIfDestroyed();
+
+        mAllPrintJobsHandled = false;
+
         if (!isBound()) {
             ensureBound();
             mPendingCommands.add(new Runnable() {
@@ -173,20 +189,18 @@
         }
     }
 
-    public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
-        mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
-                observer).sendToTarget();
+    public void createPrinterDiscoverySession() {
+        mHandler.sendEmptyMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION);
     }
 
-    private void handleCreatePrinterDiscoverySession(
-            final IPrinterDiscoverySessionObserver observer) {
+    private void handleCreatePrinterDiscoverySession() {
         throwIfDestroyed();
         if (!isBound()) {
             ensureBound();
             mPendingCommands.add(new Runnable() {
                 @Override
                 public void run() {
-                    handleCreatePrinterDiscoverySession(observer);
+                    handleCreatePrinterDiscoverySession();
                 }
             });
         } else {
@@ -194,9 +208,126 @@
                 Slog.i(LOG_TAG, "[user: " + mUserId + "] createPrinterDiscoverySession()");
             }
             try {
-                mPrintService.createPrinterDiscoverySession(observer);
+                mPrintService.createPrinterDiscoverySession();
             } catch (RemoteException re) {
-                Slog.e(LOG_TAG, "Error announcing start printer dicovery.", re);
+                Slog.e(LOG_TAG, "Error creating printer dicovery session.", re);
+            }
+
+            mHasPrinterDiscoverySession = true;
+        }
+    }
+
+    public void destroyPrinterDiscoverySession() {
+        mHandler.sendEmptyMessage(MyHandler.MSG_DESTROY_PRINTER_DISCOVERY_SESSION);
+    }
+
+    private void handleDestroyPrinterDiscoverySession() {
+        throwIfDestroyed();
+        if (!isBound()) {
+            ensureBound();
+            mPendingCommands.add(new Runnable() {
+                @Override
+                public void run() {
+                    handleDestroyPrinterDiscoverySession();
+                }
+            });
+        } else {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserId + "] destroyPrinterDiscoverySession()");
+            }
+
+            mHasPrinterDiscoverySession = false;
+
+            try {
+                mPrintService.destroyPrinterDiscoverySession();
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Error destroying printer dicovery session.", re);
+            }
+
+            // If the service has no print jobs and no active discovery
+            // session anymore we should disconnect from it.
+            if (mAllPrintJobsHandled) {
+                ensureUnbound();
+            }
+        }
+    }
+
+    public void startPrinterDiscovery(List<PrinterId> priorityList) {
+        mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_DISCOVERY,
+                priorityList).sendToTarget();
+    }
+
+    private void handleStartPrinterDiscovery(final List<PrinterId> priorityList) {
+        throwIfDestroyed();
+        if (!isBound()) {
+            ensureBound();
+            mPendingCommands.add(new Runnable() {
+                @Override
+                public void run() {
+                    handleStartPrinterDiscovery(priorityList);
+                }
+            });
+        } else {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserId + "] startPrinterDiscovery()");
+            }
+            try {
+                mPrintService.startPrinterDiscovery(priorityList);
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Error starting printer dicovery.", re);
+            }
+        }
+    }
+
+    public void stopPrinterDiscovery() {
+        mHandler.sendEmptyMessage(MyHandler.MSG_STOP_PRINTER_DISCOVERY);
+    }
+
+    private void handleStopPrinterDiscovery() {
+        throwIfDestroyed();
+        if (!isBound()) {
+            ensureBound();
+            mPendingCommands.add(new Runnable() {
+                @Override
+                public void run() {
+                    handleStopPrinterDiscovery();
+                }
+            });
+        } else {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterDiscovery()");
+            }
+            try {
+                mPrintService.stopPrinterDiscovery();
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Error stopping printer dicovery.", re);
+            }
+        }
+    }
+
+    public void requestPrinterUpdate(PrinterId printerId) {
+        mHandler.obtainMessage(MyHandler.MSG_REQUEST_PRINTER_UPDATE,
+                printerId).sendToTarget();
+    }
+
+    private void handleRequestPrinterUpdate(final PrinterId printerId) {
+        throwIfDestroyed();
+        if (!isBound()) {
+            ensureBound();
+            mPendingCommands.add(new Runnable() {
+                @Override
+                public void run() {
+                    handleRequestPrinterUpdate(printerId);
+                }
+            });
+        } else {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserId + "] requestPrinterUpdate()");
+            }
+            try {
+                mPrintService.requestPrinterUpdate(printerId);
+            } catch (RemoteException re) {
+                Slog.e(LOG_TAG, "Error requesting a printer update.", re);
             }
         }
     }
@@ -279,20 +410,47 @@
     }
 
     private final class MyHandler extends Handler {
-        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 1;
-        public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 2;
-        public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
-        public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 4;
-        public static final int MSG_DESTROY = 6;
-        public static final int MSG_BINDER_DIED = 7;
+        public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1;
+        public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
+        public static final int MSG_START_PRINTER_DISCOVERY = 3;
+        public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
+        public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
+        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 6;
+        public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 7;
+        public static final int MSG_ON_PRINT_JOB_QUEUED = 8;
+        public static final int MSG_DESTROY = 9;
+        public static final int MSG_BINDER_DIED = 10;
 
         public MyHandler(Looper looper) {
             super(looper, null, false);
         }
 
         @Override
+        @SuppressWarnings("unchecked")
         public void handleMessage(Message message) {
             switch (message.what) {
+                case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+                    handleCreatePrinterDiscoverySession();
+                } break;
+
+                case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
+                    handleDestroyPrinterDiscoverySession();
+                } break;
+
+                case MSG_START_PRINTER_DISCOVERY: {
+                    List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj;
+                    handleStartPrinterDiscovery(priorityList);
+                } break;
+
+                case MSG_STOP_PRINTER_DISCOVERY: {
+                    handleStopPrinterDiscovery();
+                } break;
+
+                case MSG_REQUEST_PRINTER_UPDATE: {
+                    PrinterId printerId = (PrinterId) message.obj;
+                    handleRequestPrinterUpdate(printerId);
+                } break;
+
                 case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
                     handleOnAllPrintJobsHandled();
                 } break;
@@ -307,13 +465,6 @@
                     handleOnPrintJobQueued(printJob);
                 } break;
 
-                case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
-                    IPrinterDiscoverySessionObserver observer =
-                            (IPrinterDiscoverySessionObserver) message.obj;
-                    handleCreatePrinterDiscoverySession(new SecurePrinterDiscoverySessionObserver(
-                            mComponentName, observer));
-                } break;
-
                 case MSG_DESTROY: {
                     handleDestroy();
                 } break;
@@ -363,7 +514,7 @@
         }
 
         @Override
-        public boolean setPrintJobState(int printJobId, int state, CharSequence error) {
+        public boolean setPrintJobState(int printJobId, int state, String error) {
             RemotePrintService service = mWeakService.get();
             if (service != null) {
                 final long identity = Binder.clearCallingIdentity();
@@ -402,79 +553,70 @@
                 }
             }
         }
-    }
-
-    private static final class SecurePrinterDiscoverySessionObserver
-            extends IPrinterDiscoverySessionObserver.Stub {
-        private final ComponentName mComponentName;
-
-        private final IPrinterDiscoverySessionObserver mDecoratedObsever;
-
-        public SecurePrinterDiscoverySessionObserver(ComponentName componentName,
-                IPrinterDiscoverySessionObserver observer) {
-            mComponentName = componentName;
-            mDecoratedObsever = observer;
-        }
 
         @Override
         public void onPrintersAdded(List<PrinterInfo> printers) {
-            throwIfPrinterIdsForPrinterInfoTampered(printers);
-            try {
-                mDecoratedObsever.onPrintersAdded(printers);
-            } catch (RemoteException re) {
-                Slog.e(LOG_TAG, "Error delegating to onPrintersAdded", re);
-            }
-        }
-
-        @Override
-        public void onPrintersUpdated(List<PrinterInfo> printers) {
-            throwIfPrinterIdsForPrinterInfoTampered(printers);
-            try {
-                mDecoratedObsever.onPrintersUpdated(printers);
-            } catch (RemoteException re) {
-                Slog.e(LOG_TAG, "Error delegating to onPrintersUpdated.", re);
+            RemotePrintService service = mWeakService.get();
+            if (service != null) {
+                throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    service.mSpooler.onPrintersAdded(printers);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
         }
 
         @Override
         public void onPrintersRemoved(List<PrinterId> printerIds) {
-            throwIfPrinterIdsTampered(printerIds);
-            try {
-                mDecoratedObsever.onPrintersRemoved(printerIds);
-            } catch (RemoteException re) {
-                Slog.e(LOG_TAG, "Error delegating to onPrintersRemoved", re);
+            RemotePrintService service = mWeakService.get();
+            if (service != null) {
+                throwIfPrinterIdsTampered(service.mComponentName, printerIds);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    service.mSpooler.onPrintersRemoved(printerIds);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
         }
 
         @Override
-        public void setController(IPrinterDiscoverySessionController controller) {
-            try {
-                mDecoratedObsever.setController(controller);
-            } catch (RemoteException re) {
-                Slog.e(LOG_TAG, "Error setting controller", re);
+        public void onPrintersUpdated(List<PrinterInfo> printers) {
+            RemotePrintService service = mWeakService.get();
+            if (service != null) {
+                throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    service.mSpooler.onPrintersUpdated(printers);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
         }
 
-        private void throwIfPrinterIdsForPrinterInfoTampered(
+        private void throwIfPrinterIdsForPrinterInfoTampered(ComponentName serviceName,
                 List<PrinterInfo> printerInfos) {
             final int printerInfoCount = printerInfos.size();
             for (int i = 0; i < printerInfoCount; i++) {
                 PrinterId printerId = printerInfos.get(i).getId();
-                throwIfPrinterIdTampered(printerId);
+                throwIfPrinterIdTampered(serviceName, printerId);
             }
         }
 
-        private void throwIfPrinterIdsTampered(List<PrinterId> printerIds) {
+        private void throwIfPrinterIdsTampered(ComponentName serviceName,
+                List<PrinterId> printerIds) {
             final int printerIdCount = printerIds.size();
             for (int i = 0; i < printerIdCount; i++) {
                 PrinterId printerId = printerIds.get(i);
-                throwIfPrinterIdTampered(printerId);
+                throwIfPrinterIdTampered(serviceName, printerId);
             }
         }
 
-        private void throwIfPrinterIdTampered(PrinterId printerId) {
+        private void throwIfPrinterIdTampered(ComponentName serviceName, PrinterId printerId) {
             if (printerId == null || printerId.getServiceName() == null
-                    || !printerId.getServiceName().equals(mComponentName)) {
+                    || !printerId.getServiceName().equals(serviceName)) {
                 throw new IllegalArgumentException("Invalid printer id: " + printerId);
             }
         }
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index c932e9b..d261288 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -32,9 +32,10 @@
 import android.print.IPrintSpooler;
 import android.print.IPrintSpoolerCallbacks;
 import android.print.IPrintSpoolerClient;
-import android.print.IPrinterDiscoverySessionObserver;
 import android.print.PrintAttributes;
 import android.print.PrintJobInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
 import android.util.Slog;
 import android.util.TimedRemoteCaller;
 
@@ -92,7 +93,11 @@
     public static interface PrintSpoolerCallbacks {
         public void onPrintJobQueued(PrintJobInfo printJob);
         public void onAllPrintJobsForServiceHandled(ComponentName printService);
-        public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
+        public void createPrinterDiscoverySession();
+        public void destroyPrinterDiscoverySession();
+        public void startPrinterDiscovery(List<PrinterId> priorityList);
+        public void stopPrinterDiscovery();
+        public void requestPrinterUpdate(PrinterId printerId);
     }
 
     public RemotePrintSpooler(Context context, int userId,
@@ -209,7 +214,7 @@
         return null;
     }
 
-    public final boolean setPrintJobState(int printJobId, int state, CharSequence error) {
+    public final boolean setPrintJobState(int printJobId, int state, String error) {
         throwIfCalledOnMainThread();
         synchronized (mLock) {
             throwIfDestroyedLocked();
@@ -300,6 +305,78 @@
         }
     }
 
+    public final void onPrintersAdded(List<PrinterInfo> printers) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().onPrintersAdded(printers);
+        } catch (RemoteException re) {
+            Slog.e(LOG_TAG, "Error adding printers.", re);
+        } catch (TimeoutException te) {
+            Slog.e(LOG_TAG, "Error adding printers.", te);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+                        + "] onPrintersAdded()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
+    public final void onPrintersRemoved(List<PrinterId> printerIds) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().onPrintersRemoved(printerIds);
+        } catch (RemoteException re) {
+            Slog.e(LOG_TAG, "Error removing printers.", re);
+        } catch (TimeoutException te) {
+            Slog.e(LOG_TAG, "Error removing printers.", te);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+                        + "] onPrintersRemoved()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
+    public final void onPrintersUpdated(List<PrinterInfo> printers) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().onPrintersUpdated(printers);
+        } catch (RemoteException re) {
+            Slog.e(LOG_TAG, "Error updating printers.", re);
+        } catch (TimeoutException te) {
+            Slog.e(LOG_TAG, "Error updating printers.", te);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+                        + "] onPrintersUpdted()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
     private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
         synchronized (mLock) {
             if (mRemoteInstance != null) {
@@ -488,7 +565,7 @@
         }
 
         public boolean setPrintJobState(IPrintSpooler target, int printJobId,
-                int status, CharSequence error) throws RemoteException, TimeoutException {
+                int status, String error) throws RemoteException, TimeoutException {
             final int sequence = onBeforeRemoteCall();
             target.setPrintJobState(printJobId, status, error, mCallback, sequence);
             return getResultTimed(sequence);
@@ -597,12 +674,64 @@
         }
 
         @Override
-        public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+        public void createPrinterDiscoverySession() {
             RemotePrintSpooler spooler = mWeakSpooler.get();
             if (spooler != null) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
-                    spooler.mCallbacks.createPrinterDiscoverySession(observer);
+                    spooler.mCallbacks.createPrinterDiscoverySession();
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
+        public void destroyPrinterDiscoverySession() {
+            RemotePrintSpooler spooler = mWeakSpooler.get();
+            if (spooler != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    spooler.mCallbacks.destroyPrinterDiscoverySession();
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
+        public void startPrinterDiscovery(List<PrinterId> priorityList) {
+            RemotePrintSpooler spooler = mWeakSpooler.get();
+            if (spooler != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    spooler.mCallbacks.startPrinterDiscovery(priorityList);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
+        public void stopPrinterDiscovery() {
+            RemotePrintSpooler spooler = mWeakSpooler.get();
+            if (spooler != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    spooler.mCallbacks.stopPrinterDiscovery();
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
+        public void requestPrinterUpdate(PrinterId printerId) {
+            RemotePrintSpooler spooler = mWeakSpooler.get();
+            if (spooler != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    spooler.mCallbacks.requestPrinterUpdate(printerId);
                 } 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 ffcc9c3..9d7cfdd 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -21,8 +21,8 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.print.IPrinterDiscoverySessionObserver;
 import android.print.PrintJobInfo;
+import android.print.PrinterId;
 import android.printservice.PrintServiceInfo;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+    public void createPrinterDiscoverySession() {
         final List<RemotePrintService> services;
         synchronized (mLock) {
             throwIfDestroyedLocked();
@@ -117,7 +117,73 @@
         final int serviceCount = services.size();
         for (int i = 0; i < serviceCount; i++) {
             RemotePrintService service = services.get(i);
-            service.createPrinterDiscoverySession(observer);
+            service.createPrinterDiscoverySession();
+        }
+    }
+
+    @Override
+    public void destroyPrinterDiscoverySession() {
+        final List<RemotePrintService> services;
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mActiveServices.isEmpty()) {
+                return;
+            }
+            services = new ArrayList<RemotePrintService>(mActiveServices.values());
+        }
+        final int serviceCount = services.size();
+        for (int i = 0; i < serviceCount; i++) {
+            RemotePrintService service = services.get(i);
+            service.destroyPrinterDiscoverySession();
+        }
+    }
+
+    @Override
+    public void startPrinterDiscovery(List<PrinterId> printerIds) {
+        final List<RemotePrintService> services;
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mActiveServices.isEmpty()) {
+                return;
+            }
+            services = new ArrayList<RemotePrintService>(mActiveServices.values());
+        }
+        final int serviceCount = services.size();
+        for (int i = 0; i < serviceCount; i++) {
+            RemotePrintService service = services.get(i);
+            service.startPrinterDiscovery(printerIds);
+        }
+    }
+
+    @Override
+    public void stopPrinterDiscovery() {
+        final List<RemotePrintService> services;
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mActiveServices.isEmpty()) {
+                return;
+            }
+            services = new ArrayList<RemotePrintService>(mActiveServices.values());
+        }
+        final int serviceCount = services.size();
+        for (int i = 0; i < serviceCount; i++) {
+            RemotePrintService service = services.get(i);
+            service.stopPrinterDiscovery();
+        }
+    }
+
+    @Override
+    public void requestPrinterUpdate(PrinterId printerId) {
+        final RemotePrintService service;
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            if (mActiveServices.isEmpty()) {
+                return;
+            }
+            service = mActiveServices.get(printerId.getServiceName());
+        }
+        if (service != null) {
+            service.requestPrinterUpdate(printerId);
         }
     }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
index 9f97311..c1e7f4a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
@@ -88,8 +88,6 @@
         @Override
         protected void onDraw(Canvas canvas) {
             super.onDraw(canvas);
-            
-            Log.d("OpenGLRenderer", "Start frame");
 
             canvas.drawARGB(255, 255, 255, 255);
 
@@ -104,6 +102,13 @@
             canvas.drawPath(mPath, mMediumPaint);
             canvas.drawPath(mPath, mMediumPaint);
 
+            mPath.reset();
+            buildPath(mPath);
+
+            canvas.translate(30.0f, 30.0f);
+            canvas.drawPath(mPath, mMediumPaint);
+            canvas.drawPath(mPath, mMediumPaint);
+
             canvas.restore();
 
             for (int i = 0; i < mRandom.nextInt(20); i++) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 96616aa..4121f79 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -551,8 +551,10 @@
         int nativeInt = sManager.addNewDelegate(delegate);
 
         // and create/return a new Bitmap with it
-        return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/,
-                density);
+        // TODO: pass correct width, height, isPremultiplied
+        return new Bitmap(nativeInt, null /* buffer */, -1 /* width */, -1 /* height */, density,
+                          isMutable, true /* isPremultiplied */,
+                          null /*ninePatchChunk*/, null /* layoutBounds */);
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 461dedb..62630d6 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -20,11 +20,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.BaseNetworkStateTracker;
 import android.net.LinkCapabilities;
+import android.net.LinkInfo;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkStateTracker;
+import android.net.SamplingDataTracker;
+import android.net.WifiLinkInfo;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
@@ -37,7 +40,7 @@
  *
  * @hide
  */
-public class WifiStateTracker implements NetworkStateTracker {
+public class WifiStateTracker extends BaseNetworkStateTracker {
 
     private static final String NETWORKTYPE = "WIFI";
     private static final String TAG = "WifiStateTracker";
@@ -48,17 +51,17 @@
     private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
 
-    private LinkProperties mLinkProperties;
-    private LinkCapabilities mLinkCapabilities;
-    private NetworkInfo mNetworkInfo;
     private NetworkInfo.State mLastState = NetworkInfo.State.UNKNOWN;
 
+    private WifiInfo mWifiInfo;
+
     /* For sending events to connectivity service handler */
     private Handler mCsHandler;
-    private Context mContext;
     private BroadcastReceiver mWifiStateReceiver;
     private WifiManager mWifiManager;
 
+    private SamplingDataTracker mSamplingDataTracker = new SamplingDataTracker();
+
     public WifiStateTracker(int netType, String networkName) {
         mNetworkInfo = new NetworkInfo(netType, 0, networkName, "");
         mLinkProperties = new LinkProperties();
@@ -174,6 +177,7 @@
     /**
      * Fetch NetworkInfo for the network
      */
+    @Override
     public NetworkInfo getNetworkInfo() {
         return new NetworkInfo(mNetworkInfo);
     }
@@ -181,6 +185,7 @@
     /**
      * Fetch LinkProperties for the network
      */
+    @Override
     public LinkProperties getLinkProperties() {
         return new LinkProperties(mLinkProperties);
     }
@@ -191,11 +196,48 @@
      *
      * @return a copy of this connections capabilities, may be empty but never null.
      */
+    @Override
     public LinkCapabilities getLinkCapabilities() {
         return new LinkCapabilities(mLinkCapabilities);
     }
 
     /**
+     * Return link info
+     * @return an object of type WifiLinkInfo
+     */
+    @Override
+    public LinkInfo getLinkInfo() {
+        if (mNetworkInfo == null) {
+            // no data available yet; just return
+            return null;
+        }
+
+        WifiLinkInfo li = new WifiLinkInfo();
+        li.mNetworkType = mNetworkInfo.getType();
+
+        synchronized(mSamplingDataTracker.mSamplingDataLock) {
+            mSamplingDataTracker.setCommonLinkInfoFields(li);
+            li.mTxGood = mSamplingDataTracker.getSampledTxPacketCount();
+            li.mTxBad = mSamplingDataTracker.getSampledTxPacketErrorCount();
+        }
+
+        // li.setTheoreticalRxBandwidth(??);
+        // li.setTheoreticalTxBandwidth(??);
+
+        if (mWifiInfo != null) {
+            li.mBssid = mWifiInfo.getBSSID();
+
+            int rssi = mWifiInfo.getRssi();
+            li.mRssi = rssi;
+
+            li.mNormalizedSignalStrength = mWifiManager.calculateSignalLevel(rssi,
+                    LinkInfo.NORMALIZED_SIGNAL_STRENGTH_RANGE);
+        }
+
+        return li;
+    }
+
+    /**
      * Check if default route is set
      */
     public boolean isDefaultRouteSet() {
@@ -224,6 +266,7 @@
             if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
                         WifiManager.EXTRA_NETWORK_INFO);
+
                 mLinkProperties = intent.getParcelableExtra(
                         WifiManager.EXTRA_LINK_PROPERTIES);
                 if (mLinkProperties == null) {
@@ -234,7 +277,9 @@
                 if (mLinkCapabilities == null) {
                     mLinkCapabilities = new LinkCapabilities();
                 }
-                // don't want to send redundent state messages
+
+                mWifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
+                // don't want to send redundant state messages
                 // but send portal check detailed state notice
                 NetworkInfo.State state = mNetworkInfo.getState();
                 if (mLastState == state &&
@@ -242,13 +287,15 @@
                     return;
                 } else {
                     mLastState = state;
+                    /* lets not sample traffic data across state changes */
+                    mSamplingDataTracker.resetSamplingData();
                 }
+
                 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
                         new NetworkInfo(mNetworkInfo));
                 msg.sendToTarget();
             } else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
-                mLinkProperties = (LinkProperties) intent.getParcelableExtra(
-                        WifiManager.EXTRA_LINK_PROPERTIES);
+                mLinkProperties = intent.getParcelableExtra(WifiManager.EXTRA_LINK_PROPERTIES);
                 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
                 msg.sendToTarget();
             }
@@ -273,4 +320,15 @@
     public void supplyMessenger(Messenger messenger) {
         // not supported on this network
     }
+
+    @Override
+    public void startSampling(SamplingDataTracker.SamplingSnapshot s) {
+        mSamplingDataTracker.startSampling(s);
+    }
+
+    @Override
+    public void stopSampling(SamplingDataTracker.SamplingSnapshot s) {
+        mSamplingDataTracker.stopSampling(s);
+    }
 }
+